diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7234cce..ba9deff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: timeout-minutes: 10 name: lint 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 + 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 @@ -38,7 +38,7 @@ jobs: run: ./scripts/lint build: - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') timeout-minutes: 10 name: build permissions: diff --git a/.gitignore b/.gitignore index 95ceb18..3824f4c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .prism.log +.stdy.log _dev __pycache__ diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 9682ed8..cacb3a0 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.35" + ".": "0.0.36" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index c2e464b..32314d6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 191 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-97e920db587b07c064bef1bf31de5e110a3750ddfddc8fca26642e79e6b827f8.yml -openapi_spec_hash: 97ca16cc55271602443a4329d1e02895 -config_hash: 1a836d20bb988f001cc66d1526f71306 +configured_endpoints: 193 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-876b65a7e83beed2ddf0d639f3df62f98d4da76d26724730d8ae49ba87855b0e.yml +openapi_spec_hash: 0512773c97cda918c1017f3b972bff0c +config_hash: fee5c8b2e5f00cef705ad48c3f3b5b5a diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c02743..7cb411b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,44 @@ # Changelog +## 0.0.36 (2026-04-07) + +Full Changelog: [v0.0.35...v0.0.36](https://github.com/whopio/whopsdk-python/compare/v0.0.35...v0.0.36) + +### Features + +* **api:** api update ([dfd2e5b](https://github.com/whopio/whopsdk-python/commit/dfd2e5b1fde74bf5d93fa8195e3aa7610c8349e6)) +* **api:** api update ([c2694e3](https://github.com/whopio/whopsdk-python/commit/c2694e3e189f52f64006c5b2503b901f31fcfe71)) +* **api:** api update ([82f0234](https://github.com/whopio/whopsdk-python/commit/82f02347c686891b5ffaeacd7cd84b9bc0a314d8)) +* **api:** api update ([6aa464e](https://github.com/whopio/whopsdk-python/commit/6aa464e34ab3d27134a66157a4ca0ef4d20b810a)) +* **api:** api update ([c7b5425](https://github.com/whopio/whopsdk-python/commit/c7b5425e8257162625fd6db79079953247a05d90)) +* **api:** api update ([6ac4297](https://github.com/whopio/whopsdk-python/commit/6ac4297d8b69e3f8209c69786f7017dd10913053)) +* **api:** api update ([e733ac9](https://github.com/whopio/whopsdk-python/commit/e733ac94f3c0f71876b46145c325e597c9569541)) +* **api:** api update ([82ba7a3](https://github.com/whopio/whopsdk-python/commit/82ba7a3c12417e18a6408a32eb2c4bf160e94768)) +* **api:** api update ([10c00d9](https://github.com/whopio/whopsdk-python/commit/10c00d9e1c45709469a36ea63c624b04fa312e58)) +* **api:** api update ([91ad304](https://github.com/whopio/whopsdk-python/commit/91ad304ea92ca8916afd9e6abb17d463b1b81b58)) +* **api:** api update ([881d399](https://github.com/whopio/whopsdk-python/commit/881d399d3b01938fd43252b435935798bd3171f7)) +* **api:** api update ([cea4dc2](https://github.com/whopio/whopsdk-python/commit/cea4dc2006ad8a1819e93fa2632edc511ab9731c)) +* **api:** api update ([349533c](https://github.com/whopio/whopsdk-python/commit/349533cc0cdb665e00d6ca104292b8cf9ae4d0d0)) +* **api:** api update ([a6443ea](https://github.com/whopio/whopsdk-python/commit/a6443ea4697c674dc80a9877fd9c531a6b688d73)) +* **api:** api update ([8f4b022](https://github.com/whopio/whopsdk-python/commit/8f4b022372bee1a75d74e83334431e030ee02496)) +* **api:** api update ([f4459b0](https://github.com/whopio/whopsdk-python/commit/f4459b0d9fa3d7e4e01db71c29611d98099dfadf)) +* **api:** api update ([a391cfc](https://github.com/whopio/whopsdk-python/commit/a391cfca3a11e21d4ac80518369b44f8f6f9ee2f)) +* **api:** api update ([021294e](https://github.com/whopio/whopsdk-python/commit/021294ecc577e24f56839d852bc978b839feb7fe)) +* **api:** manual updates ([014b6bb](https://github.com/whopio/whopsdk-python/commit/014b6bba88788acb14ce8240388b8712209f66fa)) +* **internal:** implement indices array format for query and form serialization ([e8bc1d6](https://github.com/whopio/whopsdk-python/commit/e8bc1d6948d253c722be8ea0802e8187165f4a0d)) + + +### Bug Fixes + +* add missing import and response wrappers for add_free_days method ([6f857b2](https://github.com/whopio/whopsdk-python/commit/6f857b22e4db5b371779e0759ddbd82752a0acc9)) +* sanitize endpoint path params ([ca495f7](https://github.com/whopio/whopsdk-python/commit/ca495f7081478f0056efbad9c75eea30af62f9fe)) + + +### Chores + +* **ci:** skip lint on metadata-only changes ([5428231](https://github.com/whopio/whopsdk-python/commit/542823145fee2ead9f920efd00278464d8601513)) +* **internal:** update gitignore ([e409b46](https://github.com/whopio/whopsdk-python/commit/e409b46665a918b487c9e10c25dd48819398f2bc)) + ## 0.0.35 (2026-03-18) Full Changelog: [v0.0.34...v0.0.35](https://github.com/whopio/whopsdk-python/compare/v0.0.34...v0.0.35) diff --git a/api.md b/api.md index 60f2181..1d4b939 100644 --- a/api.md +++ b/api.md @@ -83,7 +83,12 @@ Methods: Types: ```python -from whop_sdk.types import InvoiceVoidResponse +from whop_sdk.types import ( + TaxIdentifierType, + InvoiceMarkPaidResponse, + InvoiceMarkUncollectibleResponse, + InvoiceVoidResponse, +) ``` Methods: @@ -91,6 +96,8 @@ Methods: - client.invoices.create(\*\*params) -> Invoice - client.invoices.retrieve(id) -> Invoice - client.invoices.list(\*\*params) -> SyncCursorPage[InvoiceListItem] +- client.invoices.mark_paid(id) -> InvoiceMarkPaidResponse +- client.invoices.mark_uncollectible(id) -> InvoiceMarkUncollectibleResponse - client.invoices.void(id) -> InvoiceVoidResponse # CourseLessonInteractions @@ -144,6 +151,7 @@ from whop_sdk.types import ( WebhookListResponse, WebhookDeleteResponse, InvoiceCreatedWebhookEvent, + InvoiceMarkedUncollectibleWebhookEvent, InvoicePaidWebhookEvent, InvoicePastDueWebhookEvent, InvoiceVoidedWebhookEvent, @@ -162,6 +170,9 @@ from whop_sdk.types import ( PayoutMethodCreatedWebhookEvent, VerificationSucceededWebhookEvent, PayoutAccountStatusUpdatedWebhookEvent, + ResolutionCenterCaseCreatedWebhookEvent, + ResolutionCenterCaseUpdatedWebhookEvent, + ResolutionCenterCaseDecidedWebhookEvent, PaymentCreatedWebhookEvent, PaymentSucceededWebhookEvent, PaymentFailedWebhookEvent, diff --git a/pyproject.toml b/pyproject.toml index 062c3d4..9056f9e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "whop-sdk" -version = "0.0.35" +version = "0.0.36" description = "The official Python library for the Whop API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/whop_sdk/_qs.py b/src/whop_sdk/_qs.py index ada6fd3..de8c99b 100644 --- a/src/whop_sdk/_qs.py +++ b/src/whop_sdk/_qs.py @@ -101,7 +101,10 @@ def _stringify_item( items.extend(self._stringify_item(key, item, opts)) return items elif array_format == "indices": - raise NotImplementedError("The array indices format is not supported yet") + items = [] + for i, item in enumerate(value): + items.extend(self._stringify_item(f"{key}[{i}]", item, opts)) + return items elif array_format == "brackets": items = [] key = key + "[]" diff --git a/src/whop_sdk/_utils/__init__.py b/src/whop_sdk/_utils/__init__.py index dc64e29..10cb66d 100644 --- a/src/whop_sdk/_utils/__init__.py +++ b/src/whop_sdk/_utils/__init__.py @@ -1,3 +1,4 @@ +from ._path import path_template as path_template from ._sync import asyncify as asyncify from ._proxy import LazyProxy as LazyProxy from ._utils import ( diff --git a/src/whop_sdk/_utils/_path.py b/src/whop_sdk/_utils/_path.py new file mode 100644 index 0000000..4d6e1e4 --- /dev/null +++ b/src/whop_sdk/_utils/_path.py @@ -0,0 +1,127 @@ +from __future__ import annotations + +import re +from typing import ( + Any, + Mapping, + Callable, +) +from urllib.parse import quote + +# Matches '.' or '..' where each dot is either literal or percent-encoded (%2e / %2E). +_DOT_SEGMENT_RE = re.compile(r"^(?:\.|%2[eE]){1,2}$") + +_PLACEHOLDER_RE = re.compile(r"\{(\w+)\}") + + +def _quote_path_segment_part(value: str) -> str: + """Percent-encode `value` for use in a URI path segment. + + Considers characters not in `pchar` set from RFC 3986 §3.3 to be unsafe. + https://datatracker.ietf.org/doc/html/rfc3986#section-3.3 + """ + # quote() already treats unreserved characters (letters, digits, and -._~) + # as safe, so we only need to add sub-delims, ':', and '@'. + # Notably, unlike the default `safe` for quote(), / is unsafe and must be quoted. + return quote(value, safe="!$&'()*+,;=:@") + + +def _quote_query_part(value: str) -> str: + """Percent-encode `value` for use in a URI query string. + + Considers &, = and characters not in `query` set from RFC 3986 §3.4 to be unsafe. + https://datatracker.ietf.org/doc/html/rfc3986#section-3.4 + """ + return quote(value, safe="!$'()*+,;:@/?") + + +def _quote_fragment_part(value: str) -> str: + """Percent-encode `value` for use in a URI fragment. + + Considers characters not in `fragment` set from RFC 3986 §3.5 to be unsafe. + https://datatracker.ietf.org/doc/html/rfc3986#section-3.5 + """ + return quote(value, safe="!$&'()*+,;=:@/?") + + +def _interpolate( + template: str, + values: Mapping[str, Any], + quoter: Callable[[str], str], +) -> str: + """Replace {name} placeholders in `template`, quoting each value with `quoter`. + + Placeholder names are looked up in `values`. + + Raises: + KeyError: If a placeholder is not found in `values`. + """ + # re.split with a capturing group returns alternating + # [text, name, text, name, ..., text] elements. + parts = _PLACEHOLDER_RE.split(template) + + for i in range(1, len(parts), 2): + name = parts[i] + if name not in values: + raise KeyError(f"a value for placeholder {{{name}}} was not provided") + val = values[name] + if val is None: + parts[i] = "null" + elif isinstance(val, bool): + parts[i] = "true" if val else "false" + else: + parts[i] = quoter(str(values[name])) + + return "".join(parts) + + +def path_template(template: str, /, **kwargs: Any) -> str: + """Interpolate {name} placeholders in `template` from keyword arguments. + + Args: + template: The template string containing {name} placeholders. + **kwargs: Keyword arguments to interpolate into the template. + + Returns: + The template with placeholders interpolated and percent-encoded. + + Safe characters for percent-encoding are dependent on the URI component. + Placeholders in path and fragment portions are percent-encoded where the `segment` + and `fragment` sets from RFC 3986 respectively are considered safe. + Placeholders in the query portion are percent-encoded where the `query` set from + RFC 3986 §3.3 is considered safe except for = and & characters. + + Raises: + KeyError: If a placeholder is not found in `kwargs`. + ValueError: If resulting path contains /./ or /../ segments (including percent-encoded dot-segments). + """ + # Split the template into path, query, and fragment portions. + fragment_template: str | None = None + query_template: str | None = None + + rest = template + if "#" in rest: + rest, fragment_template = rest.split("#", 1) + if "?" in rest: + rest, query_template = rest.split("?", 1) + path_template = rest + + # Interpolate each portion with the appropriate quoting rules. + path_result = _interpolate(path_template, kwargs, _quote_path_segment_part) + + # Reject dot-segments (. and ..) in the final assembled path. The check + # runs after interpolation so that adjacent placeholders or a mix of static + # text and placeholders that together form a dot-segment are caught. + # Also reject percent-encoded dot-segments to protect against incorrectly + # implemented normalization in servers/proxies. + for segment in path_result.split("/"): + if _DOT_SEGMENT_RE.match(segment): + raise ValueError(f"Constructed path {path_result!r} contains dot-segment {segment!r} which is not allowed") + + result = path_result + if query_template is not None: + result += "?" + _interpolate(query_template, kwargs, _quote_query_part) + if fragment_template is not None: + result += "#" + _interpolate(fragment_template, kwargs, _quote_fragment_part) + + return result diff --git a/src/whop_sdk/_version.py b/src/whop_sdk/_version.py index 057036e..75c4782 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.35" # x-release-please-version +__version__ = "0.0.36" # x-release-please-version diff --git a/src/whop_sdk/resources/affiliates/affiliates.py b/src/whop_sdk/resources/affiliates/affiliates.py index 2c184de..75b951e 100644 --- a/src/whop_sdk/resources/affiliates/affiliates.py +++ b/src/whop_sdk/resources/affiliates/affiliates.py @@ -9,7 +9,7 @@ from ...types import Status, affiliate_list_params, affiliate_create_params from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import maybe_transform, async_maybe_transform +from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from .overrides import ( OverridesResource, @@ -142,7 +142,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/affiliates/{id}", + path_template("/affiliates/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -259,7 +259,7 @@ def archive( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/affiliates/{id}/archive", + path_template("/affiliates/{id}/archive", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -296,7 +296,7 @@ def unarchive( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/affiliates/{id}/unarchive", + path_template("/affiliates/{id}/unarchive", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -408,7 +408,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/affiliates/{id}", + path_template("/affiliates/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -525,7 +525,7 @@ async def archive( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/affiliates/{id}/archive", + path_template("/affiliates/{id}/archive", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -562,7 +562,7 @@ async def unarchive( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/affiliates/{id}/unarchive", + path_template("/affiliates/{id}/unarchive", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/affiliates/overrides.py b/src/whop_sdk/resources/affiliates/overrides.py index a3158a1..351eab6 100644 --- a/src/whop_sdk/resources/affiliates/overrides.py +++ b/src/whop_sdk/resources/affiliates/overrides.py @@ -8,7 +8,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import required_args, maybe_transform, async_maybe_transform +from ..._utils import path_template, required_args, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -180,7 +180,7 @@ def create( if not path_id: raise ValueError(f"Expected a non-empty value for `path_id` but received {path_id!r}") return self._post( - f"/affiliates/{path_id}/overrides", + path_template("/affiliates/{path_id}/overrides", path_id=path_id), body=maybe_transform( { "body_id": body_id, @@ -233,7 +233,7 @@ def retrieve( if not override_id: raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}") return self._get( - f"/affiliates/{id}/overrides/{override_id}", + path_template("/affiliates/{id}/overrides/{override_id}", id=id, override_id=override_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -285,7 +285,7 @@ def update( if not override_id: raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}") return self._patch( - f"/affiliates/{id}/overrides/{override_id}", + path_template("/affiliates/{id}/overrides/{override_id}", id=id, override_id=override_id), body=maybe_transform( { "applies_to_payments": applies_to_payments, @@ -346,7 +346,7 @@ def list( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get_api_list( - f"/affiliates/{id}/overrides", + path_template("/affiliates/{id}/overrides", id=id), page=SyncCursorPage[OverrideListResponse], options=make_request_options( extra_headers=extra_headers, @@ -400,7 +400,7 @@ def delete( if not override_id: raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}") return self._delete( - f"/affiliates/{id}/overrides/{override_id}", + path_template("/affiliates/{id}/overrides/{override_id}", id=id, override_id=override_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -547,7 +547,7 @@ async def create( if not path_id: raise ValueError(f"Expected a non-empty value for `path_id` but received {path_id!r}") return await self._post( - f"/affiliates/{path_id}/overrides", + path_template("/affiliates/{path_id}/overrides", path_id=path_id), body=await async_maybe_transform( { "body_id": body_id, @@ -600,7 +600,7 @@ async def retrieve( if not override_id: raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}") return await self._get( - f"/affiliates/{id}/overrides/{override_id}", + path_template("/affiliates/{id}/overrides/{override_id}", id=id, override_id=override_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -652,7 +652,7 @@ async def update( if not override_id: raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}") return await self._patch( - f"/affiliates/{id}/overrides/{override_id}", + path_template("/affiliates/{id}/overrides/{override_id}", id=id, override_id=override_id), body=await async_maybe_transform( { "applies_to_payments": applies_to_payments, @@ -713,7 +713,7 @@ def list( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get_api_list( - f"/affiliates/{id}/overrides", + path_template("/affiliates/{id}/overrides", id=id), page=AsyncCursorPage[OverrideListResponse], options=make_request_options( extra_headers=extra_headers, @@ -767,7 +767,7 @@ async def delete( if not override_id: raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}") return await self._delete( - f"/affiliates/{id}/overrides/{override_id}", + path_template("/affiliates/{id}/overrides/{override_id}", id=id, override_id=override_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/ai_chats.py b/src/whop_sdk/resources/ai_chats.py index 6c9f4a1..16d60eb 100644 --- a/src/whop_sdk/resources/ai_chats.py +++ b/src/whop_sdk/resources/ai_chats.py @@ -9,7 +9,7 @@ from ..types import NotificationPreferences, ai_chat_list_params, ai_chat_create_params, ai_chat_update_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -135,7 +135,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/ai_chats/{id}", + path_template("/ai_chats/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -183,7 +183,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/ai_chats/{id}", + path_template("/ai_chats/{id}", id=id), body=maybe_transform( { "current_company_id": current_company_id, @@ -287,7 +287,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/ai_chats/{id}", + path_template("/ai_chats/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -402,7 +402,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/ai_chats/{id}", + path_template("/ai_chats/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -450,7 +450,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/ai_chats/{id}", + path_template("/ai_chats/{id}", id=id), body=await async_maybe_transform( { "current_company_id": current_company_id, @@ -554,7 +554,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/ai_chats/{id}", + path_template("/ai_chats/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/app_builds.py b/src/whop_sdk/resources/app_builds.py index e4e0f85..80465b2 100644 --- a/src/whop_sdk/resources/app_builds.py +++ b/src/whop_sdk/resources/app_builds.py @@ -9,7 +9,7 @@ from ..types import app_build_list_params, app_build_create_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -149,7 +149,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/app_builds/{id}", + path_template("/app_builds/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -267,7 +267,7 @@ def promote( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/app_builds/{id}/promote", + path_template("/app_builds/{id}/promote", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -395,7 +395,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/app_builds/{id}", + path_template("/app_builds/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -513,7 +513,7 @@ async def promote( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/app_builds/{id}/promote", + path_template("/app_builds/{id}/promote", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/apps.py b/src/whop_sdk/resources/apps.py index 46fd9b7..c04a53d 100644 --- a/src/whop_sdk/resources/apps.py +++ b/src/whop_sdk/resources/apps.py @@ -9,7 +9,7 @@ from ..types import AppType, app_list_params, app_create_params, app_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -145,7 +145,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/apps/{id}", + path_template("/apps/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -166,8 +166,10 @@ def update( icon: Optional[app_update_params.Icon] | Omit = omit, name: Optional[str] | Omit = omit, oauth_client_type: Optional[Literal["public", "confidential"]] | Omit = omit, + openapi_path: Optional[str] | Omit = omit, redirect_uris: Optional[SequenceNotStr[str]] | Omit = omit, required_scopes: Optional[List[Literal["read_user"]]] | Omit = omit, + skills_path: Optional[str] | Omit = omit, status: Optional[AppStatuses] | 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. @@ -208,11 +210,16 @@ def update( oauth_client_type: How this app authenticates at the OAuth token endpoint. + openapi_path: The URL path to the OpenAPI spec file of the app, such as + '/assets/openapi.json'. + redirect_uris: The whitelisted OAuth callback URLs that users are redirected to after authorizing the app required_scopes: The permission scopes the app will request from users when they install it. + skills_path: The URL path to the skills directory of the app, such as '/assets/skills/'. + status: The status of an experience interface extra_headers: Send extra headers @@ -226,7 +233,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/apps/{id}", + path_template("/apps/{id}", id=id), body=maybe_transform( { "app_store_description": app_store_description, @@ -239,8 +246,10 @@ def update( "icon": icon, "name": name, "oauth_client_type": oauth_client_type, + "openapi_path": openapi_path, "redirect_uris": redirect_uris, "required_scopes": required_scopes, + "skills_path": skills_path, "status": status, }, app_update_params.AppUpdateParams, @@ -468,7 +477,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/apps/{id}", + path_template("/apps/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -489,8 +498,10 @@ async def update( icon: Optional[app_update_params.Icon] | Omit = omit, name: Optional[str] | Omit = omit, oauth_client_type: Optional[Literal["public", "confidential"]] | Omit = omit, + openapi_path: Optional[str] | Omit = omit, redirect_uris: Optional[SequenceNotStr[str]] | Omit = omit, required_scopes: Optional[List[Literal["read_user"]]] | Omit = omit, + skills_path: Optional[str] | Omit = omit, status: Optional[AppStatuses] | 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. @@ -531,11 +542,16 @@ async def update( oauth_client_type: How this app authenticates at the OAuth token endpoint. + openapi_path: The URL path to the OpenAPI spec file of the app, such as + '/assets/openapi.json'. + redirect_uris: The whitelisted OAuth callback URLs that users are redirected to after authorizing the app required_scopes: The permission scopes the app will request from users when they install it. + skills_path: The URL path to the skills directory of the app, such as '/assets/skills/'. + status: The status of an experience interface extra_headers: Send extra headers @@ -549,7 +565,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/apps/{id}", + path_template("/apps/{id}", id=id), body=await async_maybe_transform( { "app_store_description": app_store_description, @@ -562,8 +578,10 @@ async def update( "icon": icon, "name": name, "oauth_client_type": oauth_client_type, + "openapi_path": openapi_path, "redirect_uris": redirect_uris, "required_scopes": required_scopes, + "skills_path": skills_path, "status": status, }, app_update_params.AppUpdateParams, diff --git a/src/whop_sdk/resources/authorized_users.py b/src/whop_sdk/resources/authorized_users.py index 8ccdca5..0519e3e 100644 --- a/src/whop_sdk/resources/authorized_users.py +++ b/src/whop_sdk/resources/authorized_users.py @@ -9,7 +9,7 @@ from ..types import authorized_user_list_params, authorized_user_create_params, authorized_user_delete_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -139,7 +139,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/authorized_users/{id}", + path_template("/authorized_users/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -262,7 +262,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/authorized_users/{id}", + path_template("/authorized_users/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -387,7 +387,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/authorized_users/{id}", + path_template("/authorized_users/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -510,7 +510,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/authorized_users/{id}", + path_template("/authorized_users/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/whop_sdk/resources/chat_channels.py b/src/whop_sdk/resources/chat_channels.py index 0ed7bd7..ef5da1a 100644 --- a/src/whop_sdk/resources/chat_channels.py +++ b/src/whop_sdk/resources/chat_channels.py @@ -8,7 +8,7 @@ from ..types import chat_channel_list_params, chat_channel_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -77,7 +77,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/chat_channels/{id}", + path_template("/chat_channels/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -135,7 +135,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/chat_channels/{id}", + path_template("/chat_channels/{id}", id=id), body=maybe_transform( { "ban_media": ban_media, @@ -273,7 +273,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/chat_channels/{id}", + path_template("/chat_channels/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -331,7 +331,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/chat_channels/{id}", + path_template("/chat_channels/{id}", id=id), body=await async_maybe_transform( { "ban_media": ban_media, diff --git a/src/whop_sdk/resources/checkout_configurations.py b/src/whop_sdk/resources/checkout_configurations.py index 0160628..91d5e5d 100644 --- a/src/whop_sdk/resources/checkout_configurations.py +++ b/src/whop_sdk/resources/checkout_configurations.py @@ -10,7 +10,7 @@ from ..types import checkout_configuration_list_params, checkout_configuration_create_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import required_args, maybe_transform, async_maybe_transform +from .._utils import path_template, required_args, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -55,6 +55,10 @@ def create( *, plan: checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPlan, affiliate_code: Optional[str] | Omit = omit, + checkout_styling: Optional[ + checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling + ] + | Omit = omit, currency: Optional[Currency] | Omit = omit, metadata: Optional[Dict[str, object]] | Omit = omit, mode: Literal["payment"] | Omit = omit, @@ -87,6 +91,9 @@ def create( affiliate_code: An affiliate tracking code to attribute the checkout to a specific affiliate. + checkout_styling: Checkout styling overrides for this session. Overrides plan and company + defaults. + currency: The available currencies on the platform metadata: Custom key-value metadata to attach to the checkout configuration. @@ -114,6 +121,10 @@ def create( *, plan_id: str, affiliate_code: Optional[str] | Omit = omit, + checkout_styling: Optional[ + checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling + ] + | Omit = omit, currency: Optional[Currency] | Omit = omit, metadata: Optional[Dict[str, object]] | Omit = omit, mode: Literal["payment"] | Omit = omit, @@ -147,6 +158,9 @@ def create( affiliate_code: An affiliate tracking code to attribute the checkout to a specific affiliate. + checkout_styling: Checkout styling overrides for this session. Overrides plan and company + defaults. + currency: The available currencies on the platform metadata: Custom key-value metadata to attach to the checkout configuration. @@ -174,6 +188,10 @@ def create( *, company_id: str, mode: Literal["setup"], + checkout_styling: Optional[ + checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupCheckoutStyling + ] + | Omit = omit, currency: Optional[Currency] | Omit = omit, metadata: Optional[Dict[str, object]] | Omit = omit, payment_method_configuration: Optional[ @@ -204,6 +222,9 @@ def create( company_id: The unique identifier of the company to create the checkout configuration for. Only required in setup mode. + checkout_styling: Checkout styling overrides for this session. Overrides plan and company + defaults. + currency: The available currencies on the platform metadata: Custom key-value metadata to attach to the checkout configuration. @@ -231,6 +252,12 @@ def create( *, plan: checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPlan | Omit = omit, affiliate_code: Optional[str] | Omit = omit, + checkout_styling: Optional[ + checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling + ] + | Optional[checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling] + | Optional[checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupCheckoutStyling] + | Omit = omit, currency: Optional[Currency] | Omit = omit, metadata: Optional[Dict[str, object]] | Omit = omit, mode: Literal["payment"] | Literal["setup"] | Omit = omit, @@ -259,6 +286,7 @@ def create( { "plan": plan, "affiliate_code": affiliate_code, + "checkout_styling": checkout_styling, "currency": currency, "metadata": metadata, "mode": mode, @@ -306,7 +334,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/checkout_configurations/{id}", + path_template("/checkout_configurations/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -421,6 +449,10 @@ async def create( *, plan: checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPlan, affiliate_code: Optional[str] | Omit = omit, + checkout_styling: Optional[ + checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling + ] + | Omit = omit, currency: Optional[Currency] | Omit = omit, metadata: Optional[Dict[str, object]] | Omit = omit, mode: Literal["payment"] | Omit = omit, @@ -453,6 +485,9 @@ async def create( affiliate_code: An affiliate tracking code to attribute the checkout to a specific affiliate. + checkout_styling: Checkout styling overrides for this session. Overrides plan and company + defaults. + currency: The available currencies on the platform metadata: Custom key-value metadata to attach to the checkout configuration. @@ -480,6 +515,10 @@ async def create( *, plan_id: str, affiliate_code: Optional[str] | Omit = omit, + checkout_styling: Optional[ + checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling + ] + | Omit = omit, currency: Optional[Currency] | Omit = omit, metadata: Optional[Dict[str, object]] | Omit = omit, mode: Literal["payment"] | Omit = omit, @@ -513,6 +552,9 @@ async def create( affiliate_code: An affiliate tracking code to attribute the checkout to a specific affiliate. + checkout_styling: Checkout styling overrides for this session. Overrides plan and company + defaults. + currency: The available currencies on the platform metadata: Custom key-value metadata to attach to the checkout configuration. @@ -540,6 +582,10 @@ async def create( *, company_id: str, mode: Literal["setup"], + checkout_styling: Optional[ + checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupCheckoutStyling + ] + | Omit = omit, currency: Optional[Currency] | Omit = omit, metadata: Optional[Dict[str, object]] | Omit = omit, payment_method_configuration: Optional[ @@ -570,6 +616,9 @@ async def create( company_id: The unique identifier of the company to create the checkout configuration for. Only required in setup mode. + checkout_styling: Checkout styling overrides for this session. Overrides plan and company + defaults. + currency: The available currencies on the platform metadata: Custom key-value metadata to attach to the checkout configuration. @@ -597,6 +646,12 @@ async def create( *, plan: checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPlan | Omit = omit, affiliate_code: Optional[str] | Omit = omit, + checkout_styling: Optional[ + checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling + ] + | Optional[checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling] + | Optional[checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupCheckoutStyling] + | Omit = omit, currency: Optional[Currency] | Omit = omit, metadata: Optional[Dict[str, object]] | Omit = omit, mode: Literal["payment"] | Literal["setup"] | Omit = omit, @@ -625,6 +680,7 @@ async def create( { "plan": plan, "affiliate_code": affiliate_code, + "checkout_styling": checkout_styling, "currency": currency, "metadata": metadata, "mode": mode, @@ -672,7 +728,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/checkout_configurations/{id}", + path_template("/checkout_configurations/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/companies.py b/src/whop_sdk/resources/companies.py index 37cb077..3850775 100644 --- a/src/whop_sdk/resources/companies.py +++ b/src/whop_sdk/resources/companies.py @@ -9,7 +9,7 @@ from ..types import company_list_params, company_create_params, company_update_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -152,7 +152,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/companies/{id}", + path_template("/companies/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -163,8 +163,11 @@ def update( self, id: str, *, + affiliate_application_required: Optional[bool] | Omit = omit, + affiliate_instructions: Optional[str] | Omit = omit, banner_image: Optional[company_update_params.BannerImage] | Omit = omit, description: Optional[str] | Omit = omit, + featured_affiliate_product_id: Optional[str] | Omit = omit, logo: Optional[company_update_params.Logo] | Omit = omit, route: Optional[str] | Omit = omit, send_customer_emails: Optional[bool] | Omit = omit, @@ -186,11 +189,20 @@ def update( - `company:basic:read` Args: + affiliate_application_required: Whether prospective affiliates must submit an application before they can + promote this company. + + affiliate_instructions: Guidelines and instructions shown to affiliates explaining how to promote this + company's products. + banner_image: The company's banner image. Accepts PNG or JPEG format. description: A promotional pitch displayed to potential customers on the company's store page. + featured_affiliate_product_id: The ID of the product to feature on this company's affiliate page. Pass null to + clear. + logo: The company's logo image. Accepts PNG, JPEG, or GIF format. route: The unique URL slug for the company's store page. Must be lowercase and can @@ -216,11 +228,14 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/companies/{id}", + path_template("/companies/{id}", id=id), body=maybe_transform( { + "affiliate_application_required": affiliate_application_required, + "affiliate_instructions": affiliate_instructions, "banner_image": banner_image, "description": description, + "featured_affiliate_product_id": featured_affiliate_product_id, "logo": logo, "route": route, "send_customer_emails": send_customer_emails, @@ -441,7 +456,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/companies/{id}", + path_template("/companies/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -452,8 +467,11 @@ async def update( self, id: str, *, + affiliate_application_required: Optional[bool] | Omit = omit, + affiliate_instructions: Optional[str] | Omit = omit, banner_image: Optional[company_update_params.BannerImage] | Omit = omit, description: Optional[str] | Omit = omit, + featured_affiliate_product_id: Optional[str] | Omit = omit, logo: Optional[company_update_params.Logo] | Omit = omit, route: Optional[str] | Omit = omit, send_customer_emails: Optional[bool] | Omit = omit, @@ -475,11 +493,20 @@ async def update( - `company:basic:read` Args: + affiliate_application_required: Whether prospective affiliates must submit an application before they can + promote this company. + + affiliate_instructions: Guidelines and instructions shown to affiliates explaining how to promote this + company's products. + banner_image: The company's banner image. Accepts PNG or JPEG format. description: A promotional pitch displayed to potential customers on the company's store page. + featured_affiliate_product_id: The ID of the product to feature on this company's affiliate page. Pass null to + clear. + logo: The company's logo image. Accepts PNG, JPEG, or GIF format. route: The unique URL slug for the company's store page. Must be lowercase and can @@ -505,11 +532,14 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/companies/{id}", + path_template("/companies/{id}", id=id), body=await async_maybe_transform( { + "affiliate_application_required": affiliate_application_required, + "affiliate_instructions": affiliate_instructions, "banner_image": banner_image, "description": description, + "featured_affiliate_product_id": featured_affiliate_product_id, "logo": logo, "route": route, "send_customer_emails": send_customer_emails, diff --git a/src/whop_sdk/resources/company_token_transactions.py b/src/whop_sdk/resources/company_token_transactions.py index aa7bf6c..2b3cbdd 100644 --- a/src/whop_sdk/resources/company_token_transactions.py +++ b/src/whop_sdk/resources/company_token_transactions.py @@ -13,7 +13,7 @@ company_token_transaction_create_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import required_args, maybe_transform, async_maybe_transform +from .._utils import path_template, required_args, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -281,7 +281,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/company_token_transactions/{id}", + path_template("/company_token_transactions/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -614,7 +614,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/company_token_transactions/{id}", + path_template("/company_token_transactions/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/course_chapters.py b/src/whop_sdk/resources/course_chapters.py index 9d8345b..41c7ea1 100644 --- a/src/whop_sdk/resources/course_chapters.py +++ b/src/whop_sdk/resources/course_chapters.py @@ -8,7 +8,7 @@ from ..types import course_chapter_list_params, course_chapter_create_params, course_chapter_update_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -124,7 +124,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/course_chapters/{id}", + path_template("/course_chapters/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -164,7 +164,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/course_chapters/{id}", + path_template("/course_chapters/{id}", id=id), body=maybe_transform({"title": title}, course_chapter_update_params.CourseChapterUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -265,7 +265,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/course_chapters/{id}", + path_template("/course_chapters/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -371,7 +371,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/course_chapters/{id}", + path_template("/course_chapters/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -411,7 +411,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/course_chapters/{id}", + path_template("/course_chapters/{id}", id=id), body=await async_maybe_transform({"title": title}, course_chapter_update_params.CourseChapterUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -512,7 +512,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/course_chapters/{id}", + path_template("/course_chapters/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/course_lesson_interactions.py b/src/whop_sdk/resources/course_lesson_interactions.py index 19d4943..0b19bce 100644 --- a/src/whop_sdk/resources/course_lesson_interactions.py +++ b/src/whop_sdk/resources/course_lesson_interactions.py @@ -8,7 +8,7 @@ from ..types import course_lesson_interaction_list_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform +from .._utils import path_template, maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -76,7 +76,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/course_lesson_interactions/{id}", + path_template("/course_lesson_interactions/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -212,7 +212,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/course_lesson_interactions/{id}", + path_template("/course_lesson_interactions/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/course_lessons.py b/src/whop_sdk/resources/course_lessons.py index ef47ad3..443134b 100644 --- a/src/whop_sdk/resources/course_lessons.py +++ b/src/whop_sdk/resources/course_lessons.py @@ -16,7 +16,7 @@ course_lesson_submit_assessment_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -166,7 +166,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/course_lessons/{id}", + path_template("/course_lessons/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -254,7 +254,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/course_lessons/{id}", + path_template("/course_lessons/{id}", id=id), body=maybe_transform( { "assessment_completion_requirement": assessment_completion_requirement, @@ -378,7 +378,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/course_lessons/{id}", + path_template("/course_lessons/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -411,7 +411,7 @@ def mark_as_completed( if not lesson_id: raise ValueError(f"Expected a non-empty value for `lesson_id` but received {lesson_id!r}") return self._post( - f"/course_lessons/{lesson_id}/mark_as_completed", + path_template("/course_lessons/{lesson_id}/mark_as_completed", lesson_id=lesson_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -445,7 +445,7 @@ def start( if not lesson_id: raise ValueError(f"Expected a non-empty value for `lesson_id` but received {lesson_id!r}") return self._post( - f"/course_lessons/{lesson_id}/start", + path_template("/course_lessons/{lesson_id}/start", lesson_id=lesson_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -481,7 +481,7 @@ def submit_assessment( if not lesson_id: raise ValueError(f"Expected a non-empty value for `lesson_id` but received {lesson_id!r}") return self._post( - f"/course_lessons/{lesson_id}/submit_assessment", + path_template("/course_lessons/{lesson_id}/submit_assessment", lesson_id=lesson_id), body=maybe_transform( {"answers": answers}, course_lesson_submit_assessment_params.CourseLessonSubmitAssessmentParams ), @@ -618,7 +618,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/course_lessons/{id}", + path_template("/course_lessons/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -706,7 +706,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/course_lessons/{id}", + path_template("/course_lessons/{id}", id=id), body=await async_maybe_transform( { "assessment_completion_requirement": assessment_completion_requirement, @@ -830,7 +830,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/course_lessons/{id}", + path_template("/course_lessons/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -863,7 +863,7 @@ async def mark_as_completed( if not lesson_id: raise ValueError(f"Expected a non-empty value for `lesson_id` but received {lesson_id!r}") return await self._post( - f"/course_lessons/{lesson_id}/mark_as_completed", + path_template("/course_lessons/{lesson_id}/mark_as_completed", lesson_id=lesson_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -897,7 +897,7 @@ async def start( if not lesson_id: raise ValueError(f"Expected a non-empty value for `lesson_id` but received {lesson_id!r}") return await self._post( - f"/course_lessons/{lesson_id}/start", + path_template("/course_lessons/{lesson_id}/start", lesson_id=lesson_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -933,7 +933,7 @@ async def submit_assessment( if not lesson_id: raise ValueError(f"Expected a non-empty value for `lesson_id` but received {lesson_id!r}") return await self._post( - f"/course_lessons/{lesson_id}/submit_assessment", + path_template("/course_lessons/{lesson_id}/submit_assessment", lesson_id=lesson_id), body=await async_maybe_transform( {"answers": answers}, course_lesson_submit_assessment_params.CourseLessonSubmitAssessmentParams ), diff --git a/src/whop_sdk/resources/course_students.py b/src/whop_sdk/resources/course_students.py index 83c1656..a7c111a 100644 --- a/src/whop_sdk/resources/course_students.py +++ b/src/whop_sdk/resources/course_students.py @@ -8,7 +8,7 @@ from ..types import course_student_list_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform +from .._utils import path_template, maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -76,7 +76,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/course_students/{id}", + path_template("/course_students/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -204,7 +204,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/course_students/{id}", + path_template("/course_students/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/courses.py b/src/whop_sdk/resources/courses.py index a5c5b25..f8957ca 100644 --- a/src/whop_sdk/resources/courses.py +++ b/src/whop_sdk/resources/courses.py @@ -8,7 +8,7 @@ from ..types import Languages, CourseVisibilities, course_list_params, course_create_params, course_update_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -156,7 +156,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/courses/{id}", + path_template("/courses/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -229,7 +229,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/courses/{id}", + path_template("/courses/{id}", id=id), body=maybe_transform( { "certificate_after_completion_enabled": certificate_after_completion_enabled, @@ -350,7 +350,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/courses/{id}", + path_template("/courses/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -486,7 +486,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/courses/{id}", + path_template("/courses/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -559,7 +559,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/courses/{id}", + path_template("/courses/{id}", id=id), body=await async_maybe_transform( { "certificate_after_completion_enabled": certificate_after_completion_enabled, @@ -680,7 +680,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/courses/{id}", + path_template("/courses/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/dispute_alerts.py b/src/whop_sdk/resources/dispute_alerts.py index 03b47ef..7bfc7a6 100644 --- a/src/whop_sdk/resources/dispute_alerts.py +++ b/src/whop_sdk/resources/dispute_alerts.py @@ -9,7 +9,7 @@ from ..types import dispute_alert_list_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform +from .._utils import path_template, maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -82,7 +82,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/dispute_alerts/{id}", + path_template("/dispute_alerts/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -223,7 +223,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/dispute_alerts/{id}", + path_template("/dispute_alerts/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/disputes.py b/src/whop_sdk/resources/disputes.py index 0baa88d..81cfc21 100644 --- a/src/whop_sdk/resources/disputes.py +++ b/src/whop_sdk/resources/disputes.py @@ -9,7 +9,7 @@ from ..types import dispute_list_params, dispute_update_evidence_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -84,7 +84,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/disputes/{id}", + path_template("/disputes/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -211,7 +211,7 @@ def submit_evidence( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/disputes/{id}/submit_evidence", + path_template("/disputes/{id}/submit_evidence", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -300,7 +300,7 @@ def update_evidence( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/disputes/{id}/update_evidence", + path_template("/disputes/{id}/update_evidence", id=id), body=maybe_transform( { "access_activity_log": access_activity_log, @@ -384,7 +384,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/disputes/{id}", + path_template("/disputes/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -511,7 +511,7 @@ async def submit_evidence( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/disputes/{id}/submit_evidence", + path_template("/disputes/{id}/submit_evidence", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -600,7 +600,7 @@ async def update_evidence( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/disputes/{id}/update_evidence", + path_template("/disputes/{id}/update_evidence", id=id), body=await async_maybe_transform( { "access_activity_log": access_activity_log, diff --git a/src/whop_sdk/resources/dm_channels.py b/src/whop_sdk/resources/dm_channels.py index 7e51c55..1bae5de 100644 --- a/src/whop_sdk/resources/dm_channels.py +++ b/src/whop_sdk/resources/dm_channels.py @@ -8,7 +8,7 @@ from ..types import dm_channel_list_params, dm_channel_create_params, dm_channel_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -126,7 +126,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/dm_channels/{id}", + path_template("/dm_channels/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -168,7 +168,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/dm_channels/{id}", + path_template("/dm_channels/{id}", id=id), body=maybe_transform({"custom_name": custom_name}, dm_channel_update_params.DmChannelUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -273,7 +273,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/dm_channels/{id}", + path_template("/dm_channels/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -381,7 +381,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/dm_channels/{id}", + path_template("/dm_channels/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -423,7 +423,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/dm_channels/{id}", + path_template("/dm_channels/{id}", id=id), body=await async_maybe_transform( {"custom_name": custom_name}, dm_channel_update_params.DmChannelUpdateParams ), @@ -530,7 +530,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/dm_channels/{id}", + path_template("/dm_channels/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/dm_members.py b/src/whop_sdk/resources/dm_members.py index f1a8ca1..be2de9b 100644 --- a/src/whop_sdk/resources/dm_members.py +++ b/src/whop_sdk/resources/dm_members.py @@ -14,7 +14,7 @@ dm_member_update_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -134,7 +134,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/dm_members/{id}", + path_template("/dm_members/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -178,7 +178,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/dm_members/{id}", + path_template("/dm_members/{id}", id=id), body=maybe_transform( { "notification_preference": notification_preference, @@ -288,7 +288,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/dm_members/{id}", + path_template("/dm_members/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -396,7 +396,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/dm_members/{id}", + path_template("/dm_members/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -440,7 +440,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/dm_members/{id}", + path_template("/dm_members/{id}", id=id), body=await async_maybe_transform( { "notification_preference": notification_preference, @@ -550,7 +550,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/dm_members/{id}", + path_template("/dm_members/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/entries.py b/src/whop_sdk/resources/entries.py index 41d5d23..6847354 100644 --- a/src/whop_sdk/resources/entries.py +++ b/src/whop_sdk/resources/entries.py @@ -10,7 +10,7 @@ from ..types import entry_list_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import maybe_transform +from .._utils import path_template, maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -81,7 +81,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/entries/{id}", + path_template("/entries/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -212,7 +212,7 @@ def approve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/entries/{id}/approve", + path_template("/entries/{id}/approve", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -252,7 +252,7 @@ def deny( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/entries/{id}/deny", + path_template("/entries/{id}/deny", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -311,7 +311,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/entries/{id}", + path_template("/entries/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -442,7 +442,7 @@ async def approve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/entries/{id}/approve", + path_template("/entries/{id}/approve", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -482,7 +482,7 @@ async def deny( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/entries/{id}/deny", + path_template("/entries/{id}/deny", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/experiences.py b/src/whop_sdk/resources/experiences.py index 50542d1..b8444bd 100644 --- a/src/whop_sdk/resources/experiences.py +++ b/src/whop_sdk/resources/experiences.py @@ -17,7 +17,7 @@ experience_duplicate_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -142,7 +142,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/experiences/{id}", + path_template("/experiences/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -195,7 +195,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/experiences/{id}", + path_template("/experiences/{id}", id=id), body=maybe_transform( { "access_level": access_level, @@ -317,7 +317,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/experiences/{id}", + path_template("/experiences/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -358,7 +358,7 @@ def attach( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/experiences/{id}/attach", + path_template("/experiences/{id}/attach", id=id), body=maybe_transform({"product_id": product_id}, experience_attach_params.ExperienceAttachParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -400,7 +400,7 @@ def detach( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/experiences/{id}/detach", + path_template("/experiences/{id}/detach", id=id), body=maybe_transform({"product_id": product_id}, experience_detach_params.ExperienceDetachParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -448,7 +448,7 @@ def duplicate( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/experiences/{id}/duplicate", + path_template("/experiences/{id}/duplicate", id=id), body=maybe_transform({"name": name}, experience_duplicate_params.ExperienceDuplicateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -564,7 +564,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/experiences/{id}", + path_template("/experiences/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -617,7 +617,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/experiences/{id}", + path_template("/experiences/{id}", id=id), body=await async_maybe_transform( { "access_level": access_level, @@ -739,7 +739,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/experiences/{id}", + path_template("/experiences/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -780,7 +780,7 @@ async def attach( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/experiences/{id}/attach", + path_template("/experiences/{id}/attach", id=id), body=await async_maybe_transform( {"product_id": product_id}, experience_attach_params.ExperienceAttachParams ), @@ -824,7 +824,7 @@ async def detach( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/experiences/{id}/detach", + path_template("/experiences/{id}/detach", id=id), body=await async_maybe_transform( {"product_id": product_id}, experience_detach_params.ExperienceDetachParams ), @@ -874,7 +874,7 @@ async def duplicate( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/experiences/{id}/duplicate", + path_template("/experiences/{id}/duplicate", id=id), body=await async_maybe_transform({"name": name}, experience_duplicate_params.ExperienceDuplicateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout diff --git a/src/whop_sdk/resources/fee_markups.py b/src/whop_sdk/resources/fee_markups.py index 9944dd2..63eb13e 100644 --- a/src/whop_sdk/resources/fee_markups.py +++ b/src/whop_sdk/resources/fee_markups.py @@ -8,7 +8,7 @@ from ..types import FeeMarkupType, fee_markup_list_params, fee_markup_create_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -210,7 +210,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/fee_markups/{id}", + path_template("/fee_markups/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -401,7 +401,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/fee_markups/{id}", + path_template("/fee_markups/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/files.py b/src/whop_sdk/resources/files.py index 5729ec7..5e1ad1b 100644 --- a/src/whop_sdk/resources/files.py +++ b/src/whop_sdk/resources/files.py @@ -6,7 +6,7 @@ from ..types import file_create_params from .._types import Body, Query, Headers, NotGiven, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -104,7 +104,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/files/{id}", + path_template("/files/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -194,7 +194,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/files/{id}", + path_template("/files/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/forum_posts.py b/src/whop_sdk/resources/forum_posts.py index 0acb986..eacff2d 100644 --- a/src/whop_sdk/resources/forum_posts.py +++ b/src/whop_sdk/resources/forum_posts.py @@ -13,7 +13,7 @@ forum_post_update_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -181,7 +181,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/forum_posts/{id}", + path_template("/forum_posts/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -234,7 +234,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/forum_posts/{id}", + path_template("/forum_posts/{id}", id=id), body=maybe_transform( { "attachments": attachments, @@ -475,7 +475,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/forum_posts/{id}", + path_template("/forum_posts/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -528,7 +528,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/forum_posts/{id}", + path_template("/forum_posts/{id}", id=id), body=await async_maybe_transform( { "attachments": attachments, diff --git a/src/whop_sdk/resources/forums.py b/src/whop_sdk/resources/forums.py index 3159079..15e0432 100644 --- a/src/whop_sdk/resources/forums.py +++ b/src/whop_sdk/resources/forums.py @@ -8,7 +8,7 @@ from ..types import forum_list_params, forum_update_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -78,7 +78,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/forums/{id}", + path_template("/forums/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -125,7 +125,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/forums/{id}", + path_template("/forums/{id}", id=id), body=maybe_transform( { "email_notification_preference": email_notification_preference, @@ -260,7 +260,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/forums/{id}", + path_template("/forums/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -307,7 +307,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/forums/{id}", + path_template("/forums/{id}", id=id), body=await async_maybe_transform( { "email_notification_preference": email_notification_preference, diff --git a/src/whop_sdk/resources/invoices.py b/src/whop_sdk/resources/invoices.py index aec677f..b3ef3f2 100644 --- a/src/whop_sdk/resources/invoices.py +++ b/src/whop_sdk/resources/invoices.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Union, Optional +from typing import List, Union, Iterable, Optional from datetime import datetime from typing_extensions import Literal, overload @@ -10,7 +10,7 @@ from ..types import invoice_list_params, invoice_create_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import required_args, maybe_transform, async_maybe_transform +from .._utils import path_template, required_args, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -27,6 +27,8 @@ from ..types.shared.invoice_status import InvoiceStatus from ..types.shared.collection_method import CollectionMethod from ..types.shared.invoice_list_item import InvoiceListItem +from ..types.invoice_mark_paid_response import InvoiceMarkPaidResponse +from ..types.invoice_mark_uncollectible_response import InvoiceMarkUncollectibleResponse __all__ = ["InvoicesResource", "AsyncInvoicesResource"] @@ -62,8 +64,13 @@ def create( plan: invoice_create_params.CreateInvoiceInputWithProductAndMemberIDPlan, product: invoice_create_params.CreateInvoiceInputWithProductAndMemberIDProduct, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductAndMemberIDBillingAddress] + | Omit = omit, charge_buyer_fee: Optional[bool] | Omit = omit, customer_name: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductAndMemberIDLineItem]] + | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -104,11 +111,20 @@ def create( Only valid when collection_method is charge_automatically. If not provided, the charge will be processed immediately. + billing_address: Inline billing address to create a new mailing address for this invoice. Cannot + be used together with mailing_address_id. + charge_buyer_fee: Whether to charge the customer a buyer fee on this invoice. customer_name: The name of the customer. Required when creating an invoice for a customer who is not yet a member of the company. + line_items: Optional line items that break down the invoice total. When provided, the sum of + (quantity \\** unit_price) for all items must equal the plan price. + + mailing_address_id: The unique identifier of an existing mailing address to attach to this invoice. + Cannot be used together with billing_address. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. @@ -136,8 +152,13 @@ def create( plan: invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressPlan, product: invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressProduct, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressBillingAddress] + | Omit = omit, charge_buyer_fee: Optional[bool] | Omit = omit, customer_name: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressLineItem]] + | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -178,11 +199,20 @@ def create( Only valid when collection_method is charge_automatically. If not provided, the charge will be processed immediately. + billing_address: Inline billing address to create a new mailing address for this invoice. Cannot + be used together with mailing_address_id. + charge_buyer_fee: Whether to charge the customer a buyer fee on this invoice. customer_name: The name of the customer. Required when creating an invoice for a customer who is not yet a member of the company. + line_items: Optional line items that break down the invoice total. When provided, the sum of + (quantity \\** unit_price) for all items must equal the plan price. + + mailing_address_id: The unique identifier of an existing mailing address to attach to this invoice. + Cannot be used together with billing_address. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. @@ -210,8 +240,13 @@ def create( plan: invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDPlan, product_id: str, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDBillingAddress] + | Omit = omit, charge_buyer_fee: Optional[bool] | Omit = omit, customer_name: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDLineItem]] + | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -251,11 +286,20 @@ def create( Only valid when collection_method is charge_automatically. If not provided, the charge will be processed immediately. + billing_address: Inline billing address to create a new mailing address for this invoice. Cannot + be used together with mailing_address_id. + charge_buyer_fee: Whether to charge the customer a buyer fee on this invoice. customer_name: The name of the customer. Required when creating an invoice for a customer who is not yet a member of the company. + line_items: Optional line items that break down the invoice total. When provided, the sum of + (quantity \\** unit_price) for all items must equal the plan price. + + mailing_address_id: The unique identifier of an existing mailing address to attach to this invoice. + Cannot be used together with billing_address. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. @@ -283,8 +327,13 @@ def create( plan: invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressPlan, product_id: str, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressBillingAddress] + | Omit = omit, charge_buyer_fee: Optional[bool] | Omit = omit, customer_name: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressLineItem]] + | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -324,11 +373,20 @@ def create( Only valid when collection_method is charge_automatically. If not provided, the charge will be processed immediately. + billing_address: Inline billing address to create a new mailing address for this invoice. Cannot + be used together with mailing_address_id. + charge_buyer_fee: Whether to charge the customer a buyer fee on this invoice. customer_name: The name of the customer. Required when creating an invoice for a customer who is not yet a member of the company. + line_items: Optional line items that break down the invoice total. When provided, the sum of + (quantity \\** unit_price) for all items must equal the plan price. + + mailing_address_id: The unique identifier of an existing mailing address to attach to this invoice. + Cannot be used together with billing_address. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. @@ -366,8 +424,16 @@ def create( | invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressProduct | Omit = omit, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductAndMemberIDBillingAddress] + | Optional[invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressBillingAddress] + | Optional[invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDBillingAddress] + | Optional[invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressBillingAddress] + | Omit = omit, charge_buyer_fee: Optional[bool] | Omit = omit, customer_name: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductAndMemberIDLineItem]] + | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, email_address: str | Omit = omit, @@ -390,8 +456,11 @@ def create( "plan": plan, "product": product, "automatically_finalizes_at": automatically_finalizes_at, + "billing_address": billing_address, "charge_buyer_fee": charge_buyer_fee, "customer_name": customer_name, + "line_items": line_items, + "mailing_address_id": mailing_address_id, "payment_method_id": payment_method_id, "payment_token_id": payment_token_id, "email_address": email_address, @@ -436,7 +505,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/invoices/{id}", + path_template("/invoices/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -537,6 +606,80 @@ def list( model=InvoiceListItem, ) + def mark_paid( + 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, + ) -> InvoiceMarkPaidResponse: + """ + Mark an open invoice as paid when payment was collected outside of Whop. + + Required permissions: + + - `invoice:update` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + path_template("/invoices/{id}/mark_paid", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InvoiceMarkPaidResponse, + ) + + def mark_uncollectible( + 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, + ) -> InvoiceMarkUncollectibleResponse: + """ + Mark an open invoice as uncollectible when payment is not expected. + + Required permissions: + + - `invoice:update` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + path_template("/invoices/{id}/mark_uncollectible", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InvoiceMarkUncollectibleResponse, + ) + def void( self, id: str, @@ -569,7 +712,7 @@ def void( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/invoices/{id}/void", + path_template("/invoices/{id}/void", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -608,8 +751,13 @@ async def create( plan: invoice_create_params.CreateInvoiceInputWithProductAndMemberIDPlan, product: invoice_create_params.CreateInvoiceInputWithProductAndMemberIDProduct, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductAndMemberIDBillingAddress] + | Omit = omit, charge_buyer_fee: Optional[bool] | Omit = omit, customer_name: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductAndMemberIDLineItem]] + | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -650,11 +798,20 @@ async def create( Only valid when collection_method is charge_automatically. If not provided, the charge will be processed immediately. + billing_address: Inline billing address to create a new mailing address for this invoice. Cannot + be used together with mailing_address_id. + charge_buyer_fee: Whether to charge the customer a buyer fee on this invoice. customer_name: The name of the customer. Required when creating an invoice for a customer who is not yet a member of the company. + line_items: Optional line items that break down the invoice total. When provided, the sum of + (quantity \\** unit_price) for all items must equal the plan price. + + mailing_address_id: The unique identifier of an existing mailing address to attach to this invoice. + Cannot be used together with billing_address. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. @@ -682,8 +839,13 @@ async def create( plan: invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressPlan, product: invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressProduct, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressBillingAddress] + | Omit = omit, charge_buyer_fee: Optional[bool] | Omit = omit, customer_name: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressLineItem]] + | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -724,11 +886,20 @@ async def create( Only valid when collection_method is charge_automatically. If not provided, the charge will be processed immediately. + billing_address: Inline billing address to create a new mailing address for this invoice. Cannot + be used together with mailing_address_id. + charge_buyer_fee: Whether to charge the customer a buyer fee on this invoice. customer_name: The name of the customer. Required when creating an invoice for a customer who is not yet a member of the company. + line_items: Optional line items that break down the invoice total. When provided, the sum of + (quantity \\** unit_price) for all items must equal the plan price. + + mailing_address_id: The unique identifier of an existing mailing address to attach to this invoice. + Cannot be used together with billing_address. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. @@ -756,8 +927,13 @@ async def create( plan: invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDPlan, product_id: str, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDBillingAddress] + | Omit = omit, charge_buyer_fee: Optional[bool] | Omit = omit, customer_name: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDLineItem]] + | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -797,11 +973,20 @@ async def create( Only valid when collection_method is charge_automatically. If not provided, the charge will be processed immediately. + billing_address: Inline billing address to create a new mailing address for this invoice. Cannot + be used together with mailing_address_id. + charge_buyer_fee: Whether to charge the customer a buyer fee on this invoice. customer_name: The name of the customer. Required when creating an invoice for a customer who is not yet a member of the company. + line_items: Optional line items that break down the invoice total. When provided, the sum of + (quantity \\** unit_price) for all items must equal the plan price. + + mailing_address_id: The unique identifier of an existing mailing address to attach to this invoice. + Cannot be used together with billing_address. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. @@ -829,8 +1014,13 @@ async def create( plan: invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressPlan, product_id: str, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressBillingAddress] + | Omit = omit, charge_buyer_fee: Optional[bool] | Omit = omit, customer_name: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressLineItem]] + | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -870,11 +1060,20 @@ async def create( Only valid when collection_method is charge_automatically. If not provided, the charge will be processed immediately. + billing_address: Inline billing address to create a new mailing address for this invoice. Cannot + be used together with mailing_address_id. + charge_buyer_fee: Whether to charge the customer a buyer fee on this invoice. customer_name: The name of the customer. Required when creating an invoice for a customer who is not yet a member of the company. + line_items: Optional line items that break down the invoice total. When provided, the sum of + (quantity \\** unit_price) for all items must equal the plan price. + + mailing_address_id: The unique identifier of an existing mailing address to attach to this invoice. + Cannot be used together with billing_address. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. @@ -912,8 +1111,16 @@ async def create( | invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressProduct | Omit = omit, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductAndMemberIDBillingAddress] + | Optional[invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressBillingAddress] + | Optional[invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDBillingAddress] + | Optional[invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressBillingAddress] + | Omit = omit, charge_buyer_fee: Optional[bool] | Omit = omit, customer_name: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductAndMemberIDLineItem]] + | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, email_address: str | Omit = omit, @@ -936,8 +1143,11 @@ async def create( "plan": plan, "product": product, "automatically_finalizes_at": automatically_finalizes_at, + "billing_address": billing_address, "charge_buyer_fee": charge_buyer_fee, "customer_name": customer_name, + "line_items": line_items, + "mailing_address_id": mailing_address_id, "payment_method_id": payment_method_id, "payment_token_id": payment_token_id, "email_address": email_address, @@ -982,7 +1192,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/invoices/{id}", + path_template("/invoices/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1083,6 +1293,80 @@ def list( model=InvoiceListItem, ) + async def mark_paid( + 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, + ) -> InvoiceMarkPaidResponse: + """ + Mark an open invoice as paid when payment was collected outside of Whop. + + Required permissions: + + - `invoice:update` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + path_template("/invoices/{id}/mark_paid", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InvoiceMarkPaidResponse, + ) + + async def mark_uncollectible( + 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, + ) -> InvoiceMarkUncollectibleResponse: + """ + Mark an open invoice as uncollectible when payment is not expected. + + Required permissions: + + - `invoice:update` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + path_template("/invoices/{id}/mark_uncollectible", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InvoiceMarkUncollectibleResponse, + ) + async def void( self, id: str, @@ -1115,7 +1399,7 @@ async def void( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/invoices/{id}/void", + path_template("/invoices/{id}/void", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1136,6 +1420,12 @@ def __init__(self, invoices: InvoicesResource) -> None: self.list = to_raw_response_wrapper( invoices.list, ) + self.mark_paid = to_raw_response_wrapper( + invoices.mark_paid, + ) + self.mark_uncollectible = to_raw_response_wrapper( + invoices.mark_uncollectible, + ) self.void = to_raw_response_wrapper( invoices.void, ) @@ -1154,6 +1444,12 @@ def __init__(self, invoices: AsyncInvoicesResource) -> None: self.list = async_to_raw_response_wrapper( invoices.list, ) + self.mark_paid = async_to_raw_response_wrapper( + invoices.mark_paid, + ) + self.mark_uncollectible = async_to_raw_response_wrapper( + invoices.mark_uncollectible, + ) self.void = async_to_raw_response_wrapper( invoices.void, ) @@ -1172,6 +1468,12 @@ def __init__(self, invoices: InvoicesResource) -> None: self.list = to_streamed_response_wrapper( invoices.list, ) + self.mark_paid = to_streamed_response_wrapper( + invoices.mark_paid, + ) + self.mark_uncollectible = to_streamed_response_wrapper( + invoices.mark_uncollectible, + ) self.void = to_streamed_response_wrapper( invoices.void, ) @@ -1190,6 +1492,12 @@ def __init__(self, invoices: AsyncInvoicesResource) -> None: self.list = async_to_streamed_response_wrapper( invoices.list, ) + self.mark_paid = async_to_streamed_response_wrapper( + invoices.mark_paid, + ) + self.mark_uncollectible = async_to_streamed_response_wrapper( + invoices.mark_uncollectible, + ) self.void = async_to_streamed_response_wrapper( invoices.void, ) diff --git a/src/whop_sdk/resources/leads.py b/src/whop_sdk/resources/leads.py index df6f992..d4ad590 100644 --- a/src/whop_sdk/resources/leads.py +++ b/src/whop_sdk/resources/leads.py @@ -9,7 +9,7 @@ from ..types import lead_list_params, lead_create_params, lead_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -146,7 +146,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/leads/{id}", + path_template("/leads/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -193,7 +193,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/leads/{id}", + path_template("/leads/{id}", id=id), body=maybe_transform( { "metadata": metadata, @@ -407,7 +407,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/leads/{id}", + path_template("/leads/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -454,7 +454,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/leads/{id}", + path_template("/leads/{id}", id=id), body=await async_maybe_transform( { "metadata": metadata, diff --git a/src/whop_sdk/resources/ledger_accounts.py b/src/whop_sdk/resources/ledger_accounts.py index d213b5c..778e702 100644 --- a/src/whop_sdk/resources/ledger_accounts.py +++ b/src/whop_sdk/resources/ledger_accounts.py @@ -5,6 +5,7 @@ import httpx from .._types import Body, Query, Headers, NotGiven, not_given +from .._utils import path_template from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -70,7 +71,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/ledger_accounts/{id}", + path_template("/ledger_accounts/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -129,7 +130,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/ledger_accounts/{id}", + path_template("/ledger_accounts/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/members.py b/src/whop_sdk/resources/members.py index 811f248..5fa0c04 100644 --- a/src/whop_sdk/resources/members.py +++ b/src/whop_sdk/resources/members.py @@ -10,7 +10,7 @@ from ..types import member_list_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import maybe_transform +from .._utils import path_template, maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -83,7 +83,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/members/{id}", + path_template("/members/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -259,7 +259,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/members/{id}", + path_template("/members/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/memberships.py b/src/whop_sdk/resources/memberships.py index 22af0af..c984344 100644 --- a/src/whop_sdk/resources/memberships.py +++ b/src/whop_sdk/resources/memberships.py @@ -13,9 +13,10 @@ membership_pause_params, membership_cancel_params, membership_update_params, + membership_add_free_days_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -86,7 +87,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/memberships/{id}", + path_template("/memberships/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -129,7 +130,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/memberships/{id}", + path_template("/memberships/{id}", id=id), body=maybe_transform({"metadata": metadata}, membership_update_params.MembershipUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -244,6 +245,51 @@ def list( model=MembershipListResponse, ) + def add_free_days( + self, + id: str, + *, + free_days: int, + # 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, + ) -> Membership: + """ + Add free days to extend a membership's current billing period, expiration date, + or Stripe trial. + + Required permissions: + + - `member:manage` + - `member:email:read` + - `member:basic:read` + + Args: + free_days: The number of free days to add (1-1095). Extends the billing period, expiration + date, or Stripe trial depending on plan type. + + 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("/memberships/{id}/add_free_days", id=id), + body=maybe_transform({"free_days": free_days}, membership_add_free_days_params.MembershipAddFreeDaysParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Membership, + ) + def cancel( self, id: str, @@ -280,7 +326,7 @@ def cancel( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/memberships/{id}/cancel", + path_template("/memberships/{id}/cancel", id=id), body=maybe_transform( {"cancellation_mode": cancellation_mode}, membership_cancel_params.MembershipCancelParams ), @@ -328,7 +374,7 @@ def pause( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/memberships/{id}/pause", + path_template("/memberships/{id}/pause", id=id), body=maybe_transform({"void_payments": void_payments}, membership_pause_params.MembershipPauseParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -370,7 +416,7 @@ def resume( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/memberships/{id}/resume", + path_template("/memberships/{id}/resume", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -410,7 +456,7 @@ def uncancel( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/memberships/{id}/uncancel", + path_template("/memberships/{id}/uncancel", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -469,7 +515,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/memberships/{id}", + path_template("/memberships/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -512,7 +558,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/memberships/{id}", + path_template("/memberships/{id}", id=id), body=await async_maybe_transform({"metadata": metadata}, membership_update_params.MembershipUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -627,6 +673,53 @@ def list( model=MembershipListResponse, ) + async def add_free_days( + self, + id: str, + *, + free_days: int, + # 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, + ) -> Membership: + """ + Add free days to extend a membership's current billing period, expiration date, + or Stripe trial. + + Required permissions: + + - `member:manage` + - `member:email:read` + - `member:basic:read` + + Args: + free_days: The number of free days to add (1-1095). Extends the billing period, expiration + date, or Stripe trial depending on plan type. + + 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("/memberships/{id}/add_free_days", id=id), + body=await async_maybe_transform( + {"free_days": free_days}, membership_add_free_days_params.MembershipAddFreeDaysParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Membership, + ) + async def cancel( self, id: str, @@ -663,7 +756,7 @@ async def cancel( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/memberships/{id}/cancel", + path_template("/memberships/{id}/cancel", id=id), body=await async_maybe_transform( {"cancellation_mode": cancellation_mode}, membership_cancel_params.MembershipCancelParams ), @@ -711,7 +804,7 @@ async def pause( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/memberships/{id}/pause", + path_template("/memberships/{id}/pause", id=id), body=await async_maybe_transform( {"void_payments": void_payments}, membership_pause_params.MembershipPauseParams ), @@ -755,7 +848,7 @@ async def resume( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/memberships/{id}/resume", + path_template("/memberships/{id}/resume", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -795,7 +888,7 @@ async def uncancel( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/memberships/{id}/uncancel", + path_template("/memberships/{id}/uncancel", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -816,6 +909,9 @@ def __init__(self, memberships: MembershipsResource) -> None: self.list = to_raw_response_wrapper( memberships.list, ) + self.add_free_days = to_raw_response_wrapper( + memberships.add_free_days, + ) self.cancel = to_raw_response_wrapper( memberships.cancel, ) @@ -843,6 +939,9 @@ def __init__(self, memberships: AsyncMembershipsResource) -> None: self.list = async_to_raw_response_wrapper( memberships.list, ) + self.add_free_days = async_to_raw_response_wrapper( + memberships.add_free_days, + ) self.cancel = async_to_raw_response_wrapper( memberships.cancel, ) @@ -870,6 +969,9 @@ def __init__(self, memberships: MembershipsResource) -> None: self.list = to_streamed_response_wrapper( memberships.list, ) + self.add_free_days = to_streamed_response_wrapper( + memberships.add_free_days, + ) self.cancel = to_streamed_response_wrapper( memberships.cancel, ) @@ -897,6 +999,9 @@ def __init__(self, memberships: AsyncMembershipsResource) -> None: self.list = async_to_streamed_response_wrapper( memberships.list, ) + self.add_free_days = async_to_streamed_response_wrapper( + memberships.add_free_days, + ) self.cancel = async_to_streamed_response_wrapper( memberships.cancel, ) diff --git a/src/whop_sdk/resources/messages.py b/src/whop_sdk/resources/messages.py index 7331602..51e664a 100644 --- a/src/whop_sdk/resources/messages.py +++ b/src/whop_sdk/resources/messages.py @@ -8,7 +8,7 @@ from ..types import message_list_params, message_create_params, message_update_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -145,7 +145,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/messages/{id}", + path_template("/messages/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -190,7 +190,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/messages/{id}", + path_template("/messages/{id}", id=id), body=maybe_transform( { "attachments": attachments, @@ -304,7 +304,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/messages/{id}", + path_template("/messages/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -430,7 +430,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/messages/{id}", + path_template("/messages/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -475,7 +475,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/messages/{id}", + path_template("/messages/{id}", id=id), body=await async_maybe_transform( { "attachments": attachments, @@ -589,7 +589,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/messages/{id}", + path_template("/messages/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/payment_methods.py b/src/whop_sdk/resources/payment_methods.py index 9e99365..6c75945 100644 --- a/src/whop_sdk/resources/payment_methods.py +++ b/src/whop_sdk/resources/payment_methods.py @@ -9,7 +9,7 @@ from ..types import payment_method_list_params, payment_method_retrieve_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -87,7 +87,7 @@ def retrieve( return cast( PaymentMethodRetrieveResponse, self._get( - f"/payment_methods/{id}", + path_template("/payment_methods/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -253,7 +253,7 @@ async def retrieve( return cast( PaymentMethodRetrieveResponse, await self._get( - f"/payment_methods/{id}", + path_template("/payment_methods/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/whop_sdk/resources/payments.py b/src/whop_sdk/resources/payments.py index d36041d..db84e49 100644 --- a/src/whop_sdk/resources/payments.py +++ b/src/whop_sdk/resources/payments.py @@ -10,7 +10,7 @@ from ..types import payment_list_params, payment_create_params, payment_refund_params, payment_list_fees_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import required_args, maybe_transform, async_maybe_transform +from .._utils import path_template, required_args, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -250,7 +250,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/payments/{id}", + path_template("/payments/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -277,6 +277,8 @@ def list( query: Optional[str] | Omit = omit, statuses: Optional[List[ReceiptStatus]] | Omit = omit, substatuses: Optional[List[FriendlyReceiptStatus]] | Omit = omit, + updated_after: Union[str, datetime, None] | Omit = omit, + updated_before: Union[str, datetime, None] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -335,6 +337,10 @@ def list( substatuses: Filter payments by their current substatus for more granular filtering. + updated_after: Only return payments last updated after this timestamp. + + updated_before: Only return payments last updated before this timestamp. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -370,6 +376,8 @@ def list( "query": query, "statuses": statuses, "substatuses": substatuses, + "updated_after": updated_after, + "updated_before": updated_before, }, payment_list_params.PaymentListParams, ), @@ -420,7 +428,7 @@ def list_fees( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get_api_list( - f"/payments/{id}/fees", + path_template("/payments/{id}/fees", id=id), page=SyncCursorPage[PaymentListFeesResponse], options=make_request_options( extra_headers=extra_headers, @@ -484,7 +492,7 @@ def refund( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/payments/{id}/refund", + path_template("/payments/{id}/refund", id=id), body=maybe_transform({"partial_amount": partial_amount}, payment_refund_params.PaymentRefundParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -532,7 +540,7 @@ def retry( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/payments/{id}/retry", + path_template("/payments/{id}/retry", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -579,7 +587,7 @@ def void( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/payments/{id}/void", + path_template("/payments/{id}/void", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -804,7 +812,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/payments/{id}", + path_template("/payments/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -831,6 +839,8 @@ def list( query: Optional[str] | Omit = omit, statuses: Optional[List[ReceiptStatus]] | Omit = omit, substatuses: Optional[List[FriendlyReceiptStatus]] | Omit = omit, + updated_after: Union[str, datetime, None] | Omit = omit, + updated_before: Union[str, datetime, None] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -889,6 +899,10 @@ def list( substatuses: Filter payments by their current substatus for more granular filtering. + updated_after: Only return payments last updated after this timestamp. + + updated_before: Only return payments last updated before this timestamp. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -924,6 +938,8 @@ def list( "query": query, "statuses": statuses, "substatuses": substatuses, + "updated_after": updated_after, + "updated_before": updated_before, }, payment_list_params.PaymentListParams, ), @@ -974,7 +990,7 @@ def list_fees( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get_api_list( - f"/payments/{id}/fees", + path_template("/payments/{id}/fees", id=id), page=AsyncCursorPage[PaymentListFeesResponse], options=make_request_options( extra_headers=extra_headers, @@ -1038,7 +1054,7 @@ async def refund( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/payments/{id}/refund", + path_template("/payments/{id}/refund", id=id), body=await async_maybe_transform( {"partial_amount": partial_amount}, payment_refund_params.PaymentRefundParams ), @@ -1088,7 +1104,7 @@ async def retry( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/payments/{id}/retry", + path_template("/payments/{id}/retry", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1135,7 +1151,7 @@ async def void( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/payments/{id}/void", + path_template("/payments/{id}/void", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/payout_accounts.py b/src/whop_sdk/resources/payout_accounts.py index c59b88b..a6d57c3 100644 --- a/src/whop_sdk/resources/payout_accounts.py +++ b/src/whop_sdk/resources/payout_accounts.py @@ -5,6 +5,7 @@ import httpx from .._types import Body, Query, Headers, NotGiven, not_given +from .._utils import path_template from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -71,7 +72,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/payout_accounts/{id}", + path_template("/payout_accounts/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -131,7 +132,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/payout_accounts/{id}", + path_template("/payout_accounts/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/payout_methods.py b/src/whop_sdk/resources/payout_methods.py index 0333f57..c9fce4a 100644 --- a/src/whop_sdk/resources/payout_methods.py +++ b/src/whop_sdk/resources/payout_methods.py @@ -8,7 +8,7 @@ from ..types import payout_method_list_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform +from .._utils import path_template, maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -75,7 +75,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/payout_methods/{id}", + path_template("/payout_methods/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -197,7 +197,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/payout_methods/{id}", + path_template("/payout_methods/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/plans.py b/src/whop_sdk/resources/plans.py index 413c3f8..a0f6dac 100644 --- a/src/whop_sdk/resources/plans.py +++ b/src/whop_sdk/resources/plans.py @@ -10,7 +10,7 @@ from ..types import plan_list_params, plan_create_params, plan_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -61,6 +61,7 @@ def create( company_id: str, product_id: str, billing_period: Optional[int] | Omit = omit, + checkout_styling: Optional[plan_create_params.CheckoutStyling] | Omit = omit, currency: Optional[Currency] | Omit = omit, custom_fields: Optional[Iterable[plan_create_params.CustomField]] | Omit = omit, description: Optional[str] | Omit = omit, @@ -106,6 +107,9 @@ def create( billing_period: The number of days between recurring charges. For example, 30 for monthly or 365 for yearly. + checkout_styling: Checkout styling overrides for this plan. Pass null to inherit from the company + default. + currency: The available currencies on the platform custom_fields: An array of custom field definitions to collect from customers at checkout. @@ -167,6 +171,7 @@ def create( "company_id": company_id, "product_id": product_id, "billing_period": billing_period, + "checkout_styling": checkout_styling, "currency": currency, "custom_fields": custom_fields, "description": description, @@ -225,7 +230,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/plans/{id}", + path_template("/plans/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -237,6 +242,7 @@ def update( id: str, *, billing_period: Optional[int] | Omit = omit, + checkout_styling: Optional[plan_update_params.CheckoutStyling] | Omit = omit, currency: Optional[Currency] | Omit = omit, custom_fields: Optional[Iterable[plan_update_params.CustomField]] | Omit = omit, description: Optional[str] | Omit = omit, @@ -277,6 +283,9 @@ def update( billing_period: The number of days between recurring charges. For example, 30 for monthly or 365 for yearly. + checkout_styling: Checkout styling overrides for this plan. Pass null to remove all overrides and + inherit from the company default. + currency: The available currencies on the platform custom_fields: An array of custom field definitions to collect from customers at checkout. @@ -334,10 +343,11 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/plans/{id}", + path_template("/plans/{id}", id=id), body=maybe_transform( { "billing_period": billing_period, + "checkout_styling": checkout_styling, "currency": currency, "custom_fields": custom_fields, "description": description, @@ -495,7 +505,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/plans/{id}", + path_template("/plans/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -529,6 +539,7 @@ async def create( company_id: str, product_id: str, billing_period: Optional[int] | Omit = omit, + checkout_styling: Optional[plan_create_params.CheckoutStyling] | Omit = omit, currency: Optional[Currency] | Omit = omit, custom_fields: Optional[Iterable[plan_create_params.CustomField]] | Omit = omit, description: Optional[str] | Omit = omit, @@ -574,6 +585,9 @@ async def create( billing_period: The number of days between recurring charges. For example, 30 for monthly or 365 for yearly. + checkout_styling: Checkout styling overrides for this plan. Pass null to inherit from the company + default. + currency: The available currencies on the platform custom_fields: An array of custom field definitions to collect from customers at checkout. @@ -635,6 +649,7 @@ async def create( "company_id": company_id, "product_id": product_id, "billing_period": billing_period, + "checkout_styling": checkout_styling, "currency": currency, "custom_fields": custom_fields, "description": description, @@ -693,7 +708,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/plans/{id}", + path_template("/plans/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -705,6 +720,7 @@ async def update( id: str, *, billing_period: Optional[int] | Omit = omit, + checkout_styling: Optional[plan_update_params.CheckoutStyling] | Omit = omit, currency: Optional[Currency] | Omit = omit, custom_fields: Optional[Iterable[plan_update_params.CustomField]] | Omit = omit, description: Optional[str] | Omit = omit, @@ -745,6 +761,9 @@ async def update( billing_period: The number of days between recurring charges. For example, 30 for monthly or 365 for yearly. + checkout_styling: Checkout styling overrides for this plan. Pass null to remove all overrides and + inherit from the company default. + currency: The available currencies on the platform custom_fields: An array of custom field definitions to collect from customers at checkout. @@ -802,10 +821,11 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/plans/{id}", + path_template("/plans/{id}", id=id), body=await async_maybe_transform( { "billing_period": billing_period, + "checkout_styling": checkout_styling, "currency": currency, "custom_fields": custom_fields, "description": description, @@ -963,7 +983,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/plans/{id}", + path_template("/plans/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/products.py b/src/whop_sdk/resources/products.py index 6909de0..f2dce52 100644 --- a/src/whop_sdk/resources/products.py +++ b/src/whop_sdk/resources/products.py @@ -10,7 +10,7 @@ from ..types import product_list_params, product_create_params, product_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -96,7 +96,7 @@ def create( Args: company_id: The unique identifier of the company to create this product for. - title: The display name of the product. Maximum 40 characters. + title: The display name of the product. Maximum 80 characters. collect_shipping_address: Whether the checkout flow collects a shipping address from the customer. @@ -208,7 +208,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/products/{id}", + path_template("/products/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -291,7 +291,7 @@ def update( store_page_config: Layout and display configuration for this product on the company's store page. - title: The display name of the product. Maximum 40 characters. + title: The display name of the product. Maximum 80 characters. visibility: Visibility of a resource @@ -306,7 +306,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/products/{id}", + path_template("/products/{id}", id=id), body=maybe_transform( { "collect_shipping_address": collect_shipping_address, @@ -454,7 +454,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/products/{id}", + path_template("/products/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -524,7 +524,7 @@ async def create( Args: company_id: The unique identifier of the company to create this product for. - title: The display name of the product. Maximum 40 characters. + title: The display name of the product. Maximum 80 characters. collect_shipping_address: Whether the checkout flow collects a shipping address from the customer. @@ -636,7 +636,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/products/{id}", + path_template("/products/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -719,7 +719,7 @@ async def update( store_page_config: Layout and display configuration for this product on the company's store page. - title: The display name of the product. Maximum 40 characters. + title: The display name of the product. Maximum 80 characters. visibility: Visibility of a resource @@ -734,7 +734,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/products/{id}", + path_template("/products/{id}", id=id), body=await async_maybe_transform( { "collect_shipping_address": collect_shipping_address, @@ -882,7 +882,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/products/{id}", + path_template("/products/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/promo_codes.py b/src/whop_sdk/resources/promo_codes.py index 4d8deb2..7d89304 100644 --- a/src/whop_sdk/resources/promo_codes.py +++ b/src/whop_sdk/resources/promo_codes.py @@ -9,7 +9,7 @@ from ..types import PromoCodeStatus, promo_code_list_params, promo_code_create_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -193,7 +193,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/promo_codes/{id}", + path_template("/promo_codes/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -316,7 +316,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/promo_codes/{id}", + path_template("/promo_codes/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -487,7 +487,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/promo_codes/{id}", + path_template("/promo_codes/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -610,7 +610,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/promo_codes/{id}", + path_template("/promo_codes/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/reactions.py b/src/whop_sdk/resources/reactions.py index 4688254..243ceaf 100644 --- a/src/whop_sdk/resources/reactions.py +++ b/src/whop_sdk/resources/reactions.py @@ -8,7 +8,7 @@ from ..types import reaction_list_params, reaction_create_params, reaction_delete_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -131,7 +131,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/reactions/{id}", + path_template("/reactions/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -239,7 +239,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/reactions/{id}", + path_template("/reactions/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -356,7 +356,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/reactions/{id}", + path_template("/reactions/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -464,7 +464,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/reactions/{id}", + path_template("/reactions/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/whop_sdk/resources/refunds.py b/src/whop_sdk/resources/refunds.py index ff24a70..d845816 100644 --- a/src/whop_sdk/resources/refunds.py +++ b/src/whop_sdk/resources/refunds.py @@ -9,7 +9,7 @@ from ..types import refund_list_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform +from .._utils import path_template, maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -80,7 +80,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/refunds/{id}", + path_template("/refunds/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -225,7 +225,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/refunds/{id}", + path_template("/refunds/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/resolution_center_cases.py b/src/whop_sdk/resources/resolution_center_cases.py index 3563f15..90eb6a4 100644 --- a/src/whop_sdk/resources/resolution_center_cases.py +++ b/src/whop_sdk/resources/resolution_center_cases.py @@ -9,7 +9,7 @@ from ..types import resolution_center_case_list_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform +from .._utils import path_template, maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -80,7 +80,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/resolution_center_cases/{id}", + path_template("/resolution_center_cases/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -220,7 +220,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/resolution_center_cases/{id}", + path_template("/resolution_center_cases/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/reviews.py b/src/whop_sdk/resources/reviews.py index 3ce2c4d..0ac1ea3 100644 --- a/src/whop_sdk/resources/reviews.py +++ b/src/whop_sdk/resources/reviews.py @@ -9,7 +9,7 @@ from ..types import review_list_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform +from .._utils import path_template, maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -72,7 +72,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/reviews/{id}", + path_template("/reviews/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -202,7 +202,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/reviews/{id}", + path_template("/reviews/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/setup_intents.py b/src/whop_sdk/resources/setup_intents.py index e85baf4..4c3b154 100644 --- a/src/whop_sdk/resources/setup_intents.py +++ b/src/whop_sdk/resources/setup_intents.py @@ -9,7 +9,7 @@ from ..types import setup_intent_list_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform +from .._utils import path_template, maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -79,7 +79,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/setup_intents/{id}", + path_template("/setup_intents/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -218,7 +218,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/setup_intents/{id}", + path_template("/setup_intents/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/shipments.py b/src/whop_sdk/resources/shipments.py index 1b46c63..5a4eda5 100644 --- a/src/whop_sdk/resources/shipments.py +++ b/src/whop_sdk/resources/shipments.py @@ -8,7 +8,7 @@ from ..types import shipment_list_params, shipment_create_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -131,7 +131,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/shipments/{id}", + path_template("/shipments/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -318,7 +318,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/shipments/{id}", + path_template("/shipments/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/support_channels.py b/src/whop_sdk/resources/support_channels.py index 7b5146a..7d919e4 100644 --- a/src/whop_sdk/resources/support_channels.py +++ b/src/whop_sdk/resources/support_channels.py @@ -9,7 +9,7 @@ from ..types import support_channel_list_params, support_channel_create_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -131,7 +131,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/support_channels/{id}", + path_template("/support_channels/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -320,7 +320,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/support_channels/{id}", + path_template("/support_channels/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/transfers.py b/src/whop_sdk/resources/transfers.py index 6252141..7ff65c6 100644 --- a/src/whop_sdk/resources/transfers.py +++ b/src/whop_sdk/resources/transfers.py @@ -10,7 +10,7 @@ from ..types import transfer_list_params, transfer_create_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -152,7 +152,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/transfers/{id}", + path_template("/transfers/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -369,7 +369,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/transfers/{id}", + path_template("/transfers/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/users.py b/src/whop_sdk/resources/users.py index 7091072..6414c8e 100644 --- a/src/whop_sdk/resources/users.py +++ b/src/whop_sdk/resources/users.py @@ -8,7 +8,7 @@ from ..types import user_list_params, user_update_profile_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -72,7 +72,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/users/{id}", + path_template("/users/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -169,7 +169,7 @@ def check_access( if not resource_id: raise ValueError(f"Expected a non-empty value for `resource_id` but received {resource_id!r}") return self._get( - f"/users/{id}/access/{resource_id}", + path_template("/users/{id}/access/{resource_id}", id=id, resource_id=resource_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -279,7 +279,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/users/{id}", + path_template("/users/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -376,7 +376,7 @@ async def check_access( if not resource_id: raise ValueError(f"Expected a non-empty value for `resource_id` but received {resource_id!r}") return await self._get( - f"/users/{id}/access/{resource_id}", + path_template("/users/{id}/access/{resource_id}", id=id, resource_id=resource_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/verifications.py b/src/whop_sdk/resources/verifications.py index 54364d2..9ee917e 100644 --- a/src/whop_sdk/resources/verifications.py +++ b/src/whop_sdk/resources/verifications.py @@ -8,7 +8,7 @@ from ..types import verification_list_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform +from .._utils import path_template, maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -75,7 +75,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/verifications/{id}", + path_template("/verifications/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -197,7 +197,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/verifications/{id}", + path_template("/verifications/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/webhooks.py b/src/whop_sdk/resources/webhooks.py index 340e6a6..3004144 100644 --- a/src/whop_sdk/resources/webhooks.py +++ b/src/whop_sdk/resources/webhooks.py @@ -9,7 +9,7 @@ from ..types import APIVersion, webhook_list_params, webhook_create_params, webhook_update_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._models import construct_type from .._resource import SyncAPIResource, AsyncAPIResource @@ -148,7 +148,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/webhooks/{id}", + path_template("/webhooks/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -200,7 +200,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._patch( - f"/webhooks/{id}", + path_template("/webhooks/{id}", id=id), body=maybe_transform( { "api_version": api_version, @@ -311,7 +311,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/webhooks/{id}", + path_template("/webhooks/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -460,7 +460,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/webhooks/{id}", + path_template("/webhooks/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -512,7 +512,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._patch( - f"/webhooks/{id}", + path_template("/webhooks/{id}", id=id), body=await async_maybe_transform( { "api_version": api_version, @@ -623,7 +623,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/webhooks/{id}", + path_template("/webhooks/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/resources/withdrawals.py b/src/whop_sdk/resources/withdrawals.py index 51b7425..5d76900 100644 --- a/src/whop_sdk/resources/withdrawals.py +++ b/src/whop_sdk/resources/withdrawals.py @@ -9,7 +9,7 @@ from ..types import withdrawal_list_params, withdrawal_create_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -144,7 +144,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/withdrawals/{id}", + path_template("/withdrawals/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -344,7 +344,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/withdrawals/{id}", + path_template("/withdrawals/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/whop_sdk/types/__init__.py b/src/whop_sdk/types/__init__.py index c4684b3..95e067c 100644 --- a/src/whop_sdk/types/__init__.py +++ b/src/whop_sdk/types/__init__.py @@ -133,6 +133,7 @@ from .payment_list_params import PaymentListParams as PaymentListParams from .product_list_params import ProductListParams as ProductListParams from .setup_intent_status import SetupIntentStatus as SetupIntentStatus +from .tax_identifier_type import TaxIdentifierType as TaxIdentifierType from .topup_create_params import TopupCreateParams as TopupCreateParams from .verification_status import VerificationStatus as VerificationStatus from .webhook_list_params import WebhookListParams as WebhookListParams @@ -258,6 +259,7 @@ from .fee_markup_create_response import FeeMarkupCreateResponse as FeeMarkupCreateResponse from .fee_markup_delete_response import FeeMarkupDeleteResponse as FeeMarkupDeleteResponse from .forum_post_visibility_type import ForumPostVisibilityType as ForumPostVisibilityType +from .invoice_mark_paid_response import InvoiceMarkPaidResponse as InvoiceMarkPaidResponse from .invoice_paid_webhook_event import InvoicePaidWebhookEvent as InvoicePaidWebhookEvent from .notification_create_params import NotificationCreateParams as NotificationCreateParams from .payment_list_fees_response import PaymentListFeesResponse as PaymentListFeesResponse @@ -328,6 +330,7 @@ from .payout_account_calculated_statuses import PayoutAccountCalculatedStatuses as PayoutAccountCalculatedStatuses from .resolution_center_case_list_params import ResolutionCenterCaseListParams as ResolutionCenterCaseListParams from .dispute_alert_created_webhook_event import DisputeAlertCreatedWebhookEvent as DisputeAlertCreatedWebhookEvent +from .invoice_mark_uncollectible_response import InvoiceMarkUncollectibleResponse as InvoiceMarkUncollectibleResponse from .payout_method_created_webhook_event import PayoutMethodCreatedWebhookEvent as PayoutMethodCreatedWebhookEvent from .setup_intent_canceled_webhook_event import SetupIntentCanceledWebhookEvent as SetupIntentCanceledWebhookEvent from .checkout_configuration_create_params import CheckoutConfigurationCreateParams as CheckoutConfigurationCreateParams @@ -372,12 +375,24 @@ from .resolution_center_case_retrieve_response import ( ResolutionCenterCaseRetrieveResponse as ResolutionCenterCaseRetrieveResponse, ) +from .invoice_marked_uncollectible_webhook_event import ( + InvoiceMarkedUncollectibleWebhookEvent as InvoiceMarkedUncollectibleWebhookEvent, +) from .setup_intent_requires_action_webhook_event import ( SetupIntentRequiresActionWebhookEvent as SetupIntentRequiresActionWebhookEvent, ) from .payout_account_status_updated_webhook_event import ( PayoutAccountStatusUpdatedWebhookEvent as PayoutAccountStatusUpdatedWebhookEvent, ) +from .resolution_center_case_created_webhook_event import ( + ResolutionCenterCaseCreatedWebhookEvent as ResolutionCenterCaseCreatedWebhookEvent, +) +from .resolution_center_case_decided_webhook_event import ( + ResolutionCenterCaseDecidedWebhookEvent as ResolutionCenterCaseDecidedWebhookEvent, +) +from .resolution_center_case_updated_webhook_event import ( + ResolutionCenterCaseUpdatedWebhookEvent as ResolutionCenterCaseUpdatedWebhookEvent, +) from .course_lesson_interaction_completed_webhook_event import ( CourseLessonInteractionCompletedWebhookEvent as CourseLessonInteractionCompletedWebhookEvent, ) diff --git a/src/whop_sdk/types/affiliate.py b/src/whop_sdk/types/affiliate.py index 26de2b8..e6809ff 100644 --- a/src/whop_sdk/types/affiliate.py +++ b/src/whop_sdk/types/affiliate.py @@ -39,7 +39,9 @@ class User(BaseModel): class Affiliate(BaseModel): - """An affiliate of a company or a global affiliate""" + """ + An affiliate tracks a user's referral performance and commission earnings for a company, including retention rates, revenue metrics, and payout configurations. + """ id: str """The unique identifier for the affiliate.""" @@ -54,13 +56,16 @@ class Affiliate(BaseModel): """The datetime the affiliate was created.""" customer_retention_rate: str - """How many referrals have remained since they joined as members""" + """The percentage of referred customers who are still active members""" customer_retention_rate_ninety_days: str - """A rolling 90-day retention rate for this affiliate""" + """The percentage of referred customers who remained active over the last 90 days""" monthly_recurring_revenue_usd: str - """The total MRR of the affiliate""" + """ + The monthly recurring revenue generated by this affiliate's referrals, formatted + as a USD currency string + """ status: Optional[Status] = None """Statuses for resources""" @@ -69,13 +74,19 @@ class Affiliate(BaseModel): """The total count of all overrides for this affiliate""" total_referral_earnings_usd: str - """The total earnings of the affiliate from the users they referred""" + """ + The total commission earnings paid to this affiliate, formatted as a USD + currency string + """ total_referrals_count: int """The total referrals of the affiliate""" total_revenue_usd: str - """The total revenue of the affiliate from their referrals""" + """ + The total revenue generated from this affiliate's referrals, formatted as a USD + currency string + """ updated_at: datetime """The datetime the affiliate was last updated.""" diff --git a/src/whop_sdk/types/affiliate_list_response.py b/src/whop_sdk/types/affiliate_list_response.py index 9e24c35..64b57ca 100644 --- a/src/whop_sdk/types/affiliate_list_response.py +++ b/src/whop_sdk/types/affiliate_list_response.py @@ -39,7 +39,9 @@ class User(BaseModel): class AffiliateListResponse(BaseModel): - """An affiliate of a company or a global affiliate""" + """ + An affiliate tracks a user's referral performance and commission earnings for a company, including retention rates, revenue metrics, and payout configurations. + """ id: str """The unique identifier for the affiliate.""" @@ -54,13 +56,16 @@ class AffiliateListResponse(BaseModel): """The datetime the affiliate was created.""" customer_retention_rate: str - """How many referrals have remained since they joined as members""" + """The percentage of referred customers who are still active members""" customer_retention_rate_ninety_days: str - """A rolling 90-day retention rate for this affiliate""" + """The percentage of referred customers who remained active over the last 90 days""" monthly_recurring_revenue_usd: str - """The total MRR of the affiliate""" + """ + The monthly recurring revenue generated by this affiliate's referrals, formatted + as a USD currency string + """ status: Optional[Status] = None """Statuses for resources""" @@ -69,13 +74,19 @@ class AffiliateListResponse(BaseModel): """The total count of all overrides for this affiliate""" total_referral_earnings_usd: str - """The total earnings of the affiliate from the users they referred""" + """ + The total commission earnings paid to this affiliate, formatted as a USD + currency string + """ total_referrals_count: int """The total referrals of the affiliate""" total_revenue_usd: str - """The total revenue of the affiliate from their referrals""" + """ + The total revenue generated from this affiliate's referrals, formatted as a USD + currency string + """ updated_at: datetime """The datetime the affiliate was last updated.""" diff --git a/src/whop_sdk/types/affiliates/override_create_response.py b/src/whop_sdk/types/affiliates/override_create_response.py index b7c63d4..08a85c7 100644 --- a/src/whop_sdk/types/affiliates/override_create_response.py +++ b/src/whop_sdk/types/affiliates/override_create_response.py @@ -13,7 +13,9 @@ class OverrideCreateResponse(BaseModel): - """An object storing information about the affiliate""" + """ + A commission configuration for an affiliate, defining payout terms for a specific plan or revenue share + """ id: str """The unique identifier for the affiliate override.""" @@ -31,7 +33,11 @@ class OverrideCreateResponse(BaseModel): """The type of commission (percentage or flat_fee).""" commission_value: float - """The commission value (percentage 1-100 or flat fee in dollars).""" + """The commission amount. + + A percentage (1-100) when commission_type is percentage, or a dollar amount when + flat_fee. + """ override_type: AffiliateOverrideRoles """The type of override (standard or rev_share).""" diff --git a/src/whop_sdk/types/affiliates/override_list_response.py b/src/whop_sdk/types/affiliates/override_list_response.py index 09ce176..f470429 100644 --- a/src/whop_sdk/types/affiliates/override_list_response.py +++ b/src/whop_sdk/types/affiliates/override_list_response.py @@ -13,7 +13,9 @@ class OverrideListResponse(BaseModel): - """An object storing information about the affiliate""" + """ + A commission configuration for an affiliate, defining payout terms for a specific plan or revenue share + """ id: str """The unique identifier for the affiliate override.""" @@ -31,7 +33,11 @@ class OverrideListResponse(BaseModel): """The type of commission (percentage or flat_fee).""" commission_value: float - """The commission value (percentage 1-100 or flat fee in dollars).""" + """The commission amount. + + A percentage (1-100) when commission_type is percentage, or a dollar amount when + flat_fee. + """ override_type: AffiliateOverrideRoles """The type of override (standard or rev_share).""" diff --git a/src/whop_sdk/types/affiliates/override_retrieve_response.py b/src/whop_sdk/types/affiliates/override_retrieve_response.py index 4e54c0f..61b738f 100644 --- a/src/whop_sdk/types/affiliates/override_retrieve_response.py +++ b/src/whop_sdk/types/affiliates/override_retrieve_response.py @@ -13,7 +13,9 @@ class OverrideRetrieveResponse(BaseModel): - """An object storing information about the affiliate""" + """ + A commission configuration for an affiliate, defining payout terms for a specific plan or revenue share + """ id: str """The unique identifier for the affiliate override.""" @@ -31,7 +33,11 @@ class OverrideRetrieveResponse(BaseModel): """The type of commission (percentage or flat_fee).""" commission_value: float - """The commission value (percentage 1-100 or flat fee in dollars).""" + """The commission amount. + + A percentage (1-100) when commission_type is percentage, or a dollar amount when + flat_fee. + """ override_type: AffiliateOverrideRoles """The type of override (standard or rev_share).""" diff --git a/src/whop_sdk/types/affiliates/override_update_response.py b/src/whop_sdk/types/affiliates/override_update_response.py index b9ed5c9..3b830e3 100644 --- a/src/whop_sdk/types/affiliates/override_update_response.py +++ b/src/whop_sdk/types/affiliates/override_update_response.py @@ -13,7 +13,9 @@ class OverrideUpdateResponse(BaseModel): - """An object storing information about the affiliate""" + """ + A commission configuration for an affiliate, defining payout terms for a specific plan or revenue share + """ id: str """The unique identifier for the affiliate override.""" @@ -31,7 +33,11 @@ class OverrideUpdateResponse(BaseModel): """The type of commission (percentage or flat_fee).""" commission_value: float - """The commission value (percentage 1-100 or flat fee in dollars).""" + """The commission amount. + + A percentage (1-100) when commission_type is percentage, or a dollar amount when + flat_fee. + """ override_type: AffiliateOverrideRoles """The type of override (standard or rev_share).""" diff --git a/src/whop_sdk/types/app_list_response.py b/src/whop_sdk/types/app_list_response.py index 53563e2..8a0da2e 100644 --- a/src/whop_sdk/types/app_list_response.py +++ b/src/whop_sdk/types/app_list_response.py @@ -117,6 +117,26 @@ class AppListResponse(BaseModel): Maximum 30 characters. """ + openapi_path: Optional[str] = None + """ + The URL path template for a specific view of this app, appended to the base + domain (e.g., '/experiences/[experienceId]'). Null if the specified view type is + not configured. + """ + + origin: Optional[str] = None + """ + The full origin URL for this app's proxied domain (e.g., + 'https://myapp.apps.whop.com'). Null if no proxy domain is configured. + """ + + skills_path: Optional[str] = None + """ + The URL path template for a specific view of this app, appended to the base + domain (e.g., '/experiences/[experienceId]'). Null if the specified view type is + not configured. + """ + status: AppStatuses """The current visibility status of this app on the Whop app store. diff --git a/src/whop_sdk/types/app_update_params.py b/src/whop_sdk/types/app_update_params.py index 2d5e48b..8320361 100644 --- a/src/whop_sdk/types/app_update_params.py +++ b/src/whop_sdk/types/app_update_params.py @@ -51,6 +51,12 @@ class AppUpdateParams(TypedDict, total=False): oauth_client_type: Optional[Literal["public", "confidential"]] """How this app authenticates at the OAuth token endpoint.""" + openapi_path: Optional[str] + """ + The URL path to the OpenAPI spec file of the app, such as + '/assets/openapi.json'. + """ + redirect_uris: Optional[SequenceNotStr[str]] """ The whitelisted OAuth callback URLs that users are redirected to after @@ -60,6 +66,9 @@ class AppUpdateParams(TypedDict, total=False): required_scopes: Optional[List[Literal["read_user"]]] """The permission scopes the app will request from users when they install it.""" + skills_path: Optional[str] + """The URL path to the skills directory of the app, such as '/assets/skills/'.""" + status: Optional[AppStatuses] """The status of an experience interface""" diff --git a/src/whop_sdk/types/card_brands.py b/src/whop_sdk/types/card_brands.py index 1243eea..bd4345a 100644 --- a/src/whop_sdk/types/card_brands.py +++ b/src/whop_sdk/types/card_brands.py @@ -43,5 +43,6 @@ "cabal", "hipercard", "jcblankapay", + "cmi", "unknown", ] diff --git a/src/whop_sdk/types/checkout_configuration_create_params.py b/src/whop_sdk/types/checkout_configuration_create_params.py index cf71c43..ba31559 100644 --- a/src/whop_sdk/types/checkout_configuration_create_params.py +++ b/src/whop_sdk/types/checkout_configuration_create_params.py @@ -21,10 +21,13 @@ "CreateCheckoutSessionInputModePaymentWithPlanPlanImage", "CreateCheckoutSessionInputModePaymentWithPlanPlanPaymentMethodConfiguration", "CreateCheckoutSessionInputModePaymentWithPlanPlanProduct", + "CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling", "CreateCheckoutSessionInputModePaymentWithPlanPaymentMethodConfiguration", "CreateCheckoutSessionInputModePaymentWithPlanID", + "CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling", "CreateCheckoutSessionInputModePaymentWithPlanIDPaymentMethodConfiguration", "CreateCheckoutSessionInputModeSetup", + "CreateCheckoutSessionInputModeSetupCheckoutStyling", "CreateCheckoutSessionInputModeSetupPaymentMethodConfiguration", ] @@ -38,6 +41,12 @@ class CreateCheckoutSessionInputModePaymentWithPlan(TypedDict, total=False): affiliate_code: Optional[str] """An affiliate tracking code to attribute the checkout to a specific affiliate.""" + checkout_styling: Optional[CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling] + """Checkout styling overrides for this session. + + Overrides plan and company defaults. + """ + currency: Optional[Currency] """The available currencies on the platform""" @@ -275,6 +284,22 @@ class CreateCheckoutSessionInputModePaymentWithPlanPlan(TypedDict, total=False): """Visibility of a resource""" +class CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling(TypedDict, total=False): + """Checkout styling overrides for this session. + + Overrides plan and company defaults. + """ + + border_style: Optional[Literal["rounded", "pill", "rectangular"]] + """The different border-radius styles available for checkout pages.""" + + button_color: Optional[str] + """A hex color code for the button color (e.g. #FF5733).""" + + font_family: Optional[Literal["system", "roboto", "open_sans"]] + """The different font families available for checkout pages.""" + + class CreateCheckoutSessionInputModePaymentWithPlanPaymentMethodConfiguration(TypedDict, total=False): """The explicit payment method configuration for the checkout session. @@ -313,6 +338,12 @@ class CreateCheckoutSessionInputModePaymentWithPlanID(TypedDict, total=False): affiliate_code: Optional[str] """An affiliate tracking code to attribute the checkout to a specific affiliate.""" + checkout_styling: Optional[CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling] + """Checkout styling overrides for this session. + + Overrides plan and company defaults. + """ + currency: Optional[Currency] """The available currencies on the platform""" @@ -335,6 +366,22 @@ class CreateCheckoutSessionInputModePaymentWithPlanID(TypedDict, total=False): """The URL of the page where the checkout is being initiated from.""" +class CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling(TypedDict, total=False): + """Checkout styling overrides for this session. + + Overrides plan and company defaults. + """ + + border_style: Optional[Literal["rounded", "pill", "rectangular"]] + """The different border-radius styles available for checkout pages.""" + + button_color: Optional[str] + """A hex color code for the button color (e.g. #FF5733).""" + + font_family: Optional[Literal["system", "roboto", "open_sans"]] + """The different font families available for checkout pages.""" + + class CreateCheckoutSessionInputModePaymentWithPlanIDPaymentMethodConfiguration(TypedDict, total=False): """The explicit payment method configuration for the checkout session. @@ -372,6 +419,12 @@ class CreateCheckoutSessionInputModeSetup(TypedDict, total=False): mode: Required[Literal["setup"]] + checkout_styling: Optional[CreateCheckoutSessionInputModeSetupCheckoutStyling] + """Checkout styling overrides for this session. + + Overrides plan and company defaults. + """ + currency: Optional[Currency] """The available currencies on the platform""" @@ -392,6 +445,22 @@ class CreateCheckoutSessionInputModeSetup(TypedDict, total=False): """The URL of the page where the checkout is being initiated from.""" +class CreateCheckoutSessionInputModeSetupCheckoutStyling(TypedDict, total=False): + """Checkout styling overrides for this session. + + Overrides plan and company defaults. + """ + + border_style: Optional[Literal["rounded", "pill", "rectangular"]] + """The different border-radius styles available for checkout pages.""" + + button_color: Optional[str] + """A hex color code for the button color (e.g. #FF5733).""" + + font_family: Optional[Literal["system", "roboto", "open_sans"]] + """The different font families available for checkout pages.""" + + class CreateCheckoutSessionInputModeSetupPaymentMethodConfiguration(TypedDict, total=False): """The explicit payment method configuration for the checkout session. diff --git a/src/whop_sdk/types/company_list_response.py b/src/whop_sdk/types/company_list_response.py index 197728d..52d0916 100644 --- a/src/whop_sdk/types/company_list_response.py +++ b/src/whop_sdk/types/company_list_response.py @@ -84,6 +84,9 @@ class CompanyListResponse(BaseModel): behalf of this company. """ + target_audience: Optional[str] = None + """The target audience for the company. Null if not set.""" + title: str """The display name of the company shown to customers.""" diff --git a/src/whop_sdk/types/company_update_params.py b/src/whop_sdk/types/company_update_params.py index c475d5f..15aa74d 100644 --- a/src/whop_sdk/types/company_update_params.py +++ b/src/whop_sdk/types/company_update_params.py @@ -9,6 +9,18 @@ class CompanyUpdateParams(TypedDict, total=False): + affiliate_application_required: Optional[bool] + """ + Whether prospective affiliates must submit an application before they can + promote this company. + """ + + affiliate_instructions: Optional[str] + """ + Guidelines and instructions shown to affiliates explaining how to promote this + company's products. + """ + banner_image: Optional[BannerImage] """The company's banner image. Accepts PNG or JPEG format.""" @@ -18,6 +30,12 @@ class CompanyUpdateParams(TypedDict, total=False): page. """ + featured_affiliate_product_id: Optional[str] + """The ID of the product to feature on this company's affiliate page. + + Pass null to clear. + """ + logo: Optional[Logo] """The company's logo image. Accepts PNG, JPEG, or GIF format.""" diff --git a/src/whop_sdk/types/invoice_create_params.py b/src/whop_sdk/types/invoice_create_params.py index a3c6104..a197501 100644 --- a/src/whop_sdk/types/invoice_create_params.py +++ b/src/whop_sdk/types/invoice_create_params.py @@ -9,6 +9,7 @@ from .._utils import PropertyInfo from .shared.plan_type import PlanType from .shared.visibility import Visibility +from .tax_identifier_type import TaxIdentifierType from .shared.release_method import ReleaseMethod from .shared.collection_method import CollectionMethod @@ -18,16 +19,24 @@ "CreateInvoiceInputWithProductAndMemberIDPlan", "CreateInvoiceInputWithProductAndMemberIDPlanCustomField", "CreateInvoiceInputWithProductAndMemberIDProduct", + "CreateInvoiceInputWithProductAndMemberIDBillingAddress", + "CreateInvoiceInputWithProductAndMemberIDLineItem", "CreateInvoiceInputWithProductAndEmailAddress", "CreateInvoiceInputWithProductAndEmailAddressPlan", "CreateInvoiceInputWithProductAndEmailAddressPlanCustomField", "CreateInvoiceInputWithProductAndEmailAddressProduct", + "CreateInvoiceInputWithProductAndEmailAddressBillingAddress", + "CreateInvoiceInputWithProductAndEmailAddressLineItem", "CreateInvoiceInputWithProductIDAndMemberID", "CreateInvoiceInputWithProductIDAndMemberIDPlan", "CreateInvoiceInputWithProductIDAndMemberIDPlanCustomField", + "CreateInvoiceInputWithProductIDAndMemberIDLineItem", "CreateInvoiceInputWithProductIDAndEmailAddress", "CreateInvoiceInputWithProductIDAndEmailAddressPlan", "CreateInvoiceInputWithProductIDAndEmailAddressPlanCustomField", + "CreateInvoiceInputWithProductIDAndMemberIDBillingAddress", + "CreateInvoiceInputWithProductIDAndEmailAddressBillingAddress", + "CreateInvoiceInputWithProductIDAndEmailAddressLineItem", ] @@ -70,6 +79,12 @@ class CreateInvoiceInputWithProductAndMemberID(TypedDict, total=False): charge will be processed immediately. """ + billing_address: Optional[CreateInvoiceInputWithProductAndMemberIDBillingAddress] + """Inline billing address to create a new mailing address for this invoice. + + Cannot be used together with mailing_address_id. + """ + charge_buyer_fee: Optional[bool] """Whether to charge the customer a buyer fee on this invoice.""" @@ -80,6 +95,19 @@ class CreateInvoiceInputWithProductAndMemberID(TypedDict, total=False): company. """ + line_items: Optional[Iterable[CreateInvoiceInputWithProductAndMemberIDLineItem]] + """Optional line items that break down the invoice total. + + When provided, the sum of (quantity \\** unit_price) for all items must equal the + plan price. + """ + + mailing_address_id: Optional[str] + """The unique identifier of an existing mailing address to attach to this invoice. + + Cannot be used together with billing_address. + """ + payment_method_id: Optional[str] """The unique identifier of the payment method to charge. @@ -186,6 +214,61 @@ class CreateInvoiceInputWithProductAndMemberIDProduct(TypedDict, total=False): """The ID of the product tax code to apply to this product.""" +class CreateInvoiceInputWithProductAndMemberIDBillingAddress(TypedDict, total=False): + """Inline billing address to create a new mailing address for this invoice. + + Cannot be used together with mailing_address_id. + """ + + city: Optional[str] + """The city of the address.""" + + country: Optional[str] + """The country of the address.""" + + line1: Optional[str] + """The line 1 of the address.""" + + line2: Optional[str] + """The line 2 of the address.""" + + name: Optional[str] + """The name of the customer.""" + + phone: Optional[str] + """The phone number of the customer.""" + + postal_code: Optional[str] + """The postal code of the address.""" + + state: Optional[str] + """The state of the address.""" + + tax_id_type: Optional[TaxIdentifierType] + """The type of tax identifier""" + + tax_id_value: Optional[str] + """The value of the tax identifier.""" + + +class CreateInvoiceInputWithProductAndMemberIDLineItem(TypedDict, total=False): + """ + A single line item to include on the invoice, with a label, quantity, and unit price. + """ + + label: Required[str] + """The label or description for this line item.""" + + unit_price: Required[float] + """The unit price for this line item. + + Provided as a number in the specified currency. Eg: 10.43 for $10.43 + """ + + quantity: Optional[float] + """The quantity of this line item. Defaults to 1.""" + + class CreateInvoiceInputWithProductAndEmailAddress(TypedDict, total=False): collection_method: Required[CollectionMethod] """How the invoice should be collected. @@ -226,6 +309,12 @@ class CreateInvoiceInputWithProductAndEmailAddress(TypedDict, total=False): charge will be processed immediately. """ + billing_address: Optional[CreateInvoiceInputWithProductAndEmailAddressBillingAddress] + """Inline billing address to create a new mailing address for this invoice. + + Cannot be used together with mailing_address_id. + """ + charge_buyer_fee: Optional[bool] """Whether to charge the customer a buyer fee on this invoice.""" @@ -236,6 +325,19 @@ class CreateInvoiceInputWithProductAndEmailAddress(TypedDict, total=False): company. """ + line_items: Optional[Iterable[CreateInvoiceInputWithProductAndEmailAddressLineItem]] + """Optional line items that break down the invoice total. + + When provided, the sum of (quantity \\** unit_price) for all items must equal the + plan price. + """ + + mailing_address_id: Optional[str] + """The unique identifier of an existing mailing address to attach to this invoice. + + Cannot be used together with billing_address. + """ + payment_method_id: Optional[str] """The unique identifier of the payment method to charge. @@ -342,6 +444,61 @@ class CreateInvoiceInputWithProductAndEmailAddressProduct(TypedDict, total=False """The ID of the product tax code to apply to this product.""" +class CreateInvoiceInputWithProductAndEmailAddressBillingAddress(TypedDict, total=False): + """Inline billing address to create a new mailing address for this invoice. + + Cannot be used together with mailing_address_id. + """ + + city: Optional[str] + """The city of the address.""" + + country: Optional[str] + """The country of the address.""" + + line1: Optional[str] + """The line 1 of the address.""" + + line2: Optional[str] + """The line 2 of the address.""" + + name: Optional[str] + """The name of the customer.""" + + phone: Optional[str] + """The phone number of the customer.""" + + postal_code: Optional[str] + """The postal code of the address.""" + + state: Optional[str] + """The state of the address.""" + + tax_id_type: Optional[TaxIdentifierType] + """The type of tax identifier""" + + tax_id_value: Optional[str] + """The value of the tax identifier.""" + + +class CreateInvoiceInputWithProductAndEmailAddressLineItem(TypedDict, total=False): + """ + A single line item to include on the invoice, with a label, quantity, and unit price. + """ + + label: Required[str] + """The label or description for this line item.""" + + unit_price: Required[float] + """The unit price for this line item. + + Provided as a number in the specified currency. Eg: 10.43 for $10.43 + """ + + quantity: Optional[float] + """The quantity of this line item. Defaults to 1.""" + + class CreateInvoiceInputWithProductIDAndMemberID(TypedDict, total=False): collection_method: Required[CollectionMethod] """How the invoice should be collected. @@ -378,6 +535,12 @@ class CreateInvoiceInputWithProductIDAndMemberID(TypedDict, total=False): charge will be processed immediately. """ + billing_address: Optional[CreateInvoiceInputWithProductIDAndMemberIDBillingAddress] + """Inline billing address to create a new mailing address for this invoice. + + Cannot be used together with mailing_address_id. + """ + charge_buyer_fee: Optional[bool] """Whether to charge the customer a buyer fee on this invoice.""" @@ -388,6 +551,19 @@ class CreateInvoiceInputWithProductIDAndMemberID(TypedDict, total=False): company. """ + line_items: Optional[Iterable[CreateInvoiceInputWithProductIDAndMemberIDLineItem]] + """Optional line items that break down the invoice total. + + When provided, the sum of (quantity \\** unit_price) for all items must equal the + plan price. + """ + + mailing_address_id: Optional[str] + """The unique identifier of an existing mailing address to attach to this invoice. + + Cannot be used together with billing_address. + """ + payment_method_id: Optional[str] """The unique identifier of the payment method to charge. @@ -481,6 +657,61 @@ class CreateInvoiceInputWithProductIDAndMemberIDPlan(TypedDict, total=False): """Visibility of a resource""" +class CreateInvoiceInputWithProductIDAndMemberIDBillingAddress(TypedDict, total=False): + """Inline billing address to create a new mailing address for this invoice. + + Cannot be used together with mailing_address_id. + """ + + city: Optional[str] + """The city of the address.""" + + country: Optional[str] + """The country of the address.""" + + line1: Optional[str] + """The line 1 of the address.""" + + line2: Optional[str] + """The line 2 of the address.""" + + name: Optional[str] + """The name of the customer.""" + + phone: Optional[str] + """The phone number of the customer.""" + + postal_code: Optional[str] + """The postal code of the address.""" + + state: Optional[str] + """The state of the address.""" + + tax_id_type: Optional[TaxIdentifierType] + """The type of tax identifier""" + + tax_id_value: Optional[str] + """The value of the tax identifier.""" + + +class CreateInvoiceInputWithProductIDAndMemberIDLineItem(TypedDict, total=False): + """ + A single line item to include on the invoice, with a label, quantity, and unit price. + """ + + label: Required[str] + """The label or description for this line item.""" + + unit_price: Required[float] + """The unit price for this line item. + + Provided as a number in the specified currency. Eg: 10.43 for $10.43 + """ + + quantity: Optional[float] + """The quantity of this line item. Defaults to 1.""" + + class CreateInvoiceInputWithProductIDAndEmailAddress(TypedDict, total=False): collection_method: Required[CollectionMethod] """How the invoice should be collected. @@ -518,6 +749,12 @@ class CreateInvoiceInputWithProductIDAndEmailAddress(TypedDict, total=False): charge will be processed immediately. """ + billing_address: Optional[CreateInvoiceInputWithProductIDAndEmailAddressBillingAddress] + """Inline billing address to create a new mailing address for this invoice. + + Cannot be used together with mailing_address_id. + """ + charge_buyer_fee: Optional[bool] """Whether to charge the customer a buyer fee on this invoice.""" @@ -528,6 +765,19 @@ class CreateInvoiceInputWithProductIDAndEmailAddress(TypedDict, total=False): company. """ + line_items: Optional[Iterable[CreateInvoiceInputWithProductIDAndEmailAddressLineItem]] + """Optional line items that break down the invoice total. + + When provided, the sum of (quantity \\** unit_price) for all items must equal the + plan price. + """ + + mailing_address_id: Optional[str] + """The unique identifier of an existing mailing address to attach to this invoice. + + Cannot be used together with billing_address. + """ + payment_method_id: Optional[str] """The unique identifier of the payment method to charge. @@ -621,6 +871,61 @@ class CreateInvoiceInputWithProductIDAndEmailAddressPlan(TypedDict, total=False) """Visibility of a resource""" +class CreateInvoiceInputWithProductIDAndEmailAddressBillingAddress(TypedDict, total=False): + """Inline billing address to create a new mailing address for this invoice. + + Cannot be used together with mailing_address_id. + """ + + city: Optional[str] + """The city of the address.""" + + country: Optional[str] + """The country of the address.""" + + line1: Optional[str] + """The line 1 of the address.""" + + line2: Optional[str] + """The line 2 of the address.""" + + name: Optional[str] + """The name of the customer.""" + + phone: Optional[str] + """The phone number of the customer.""" + + postal_code: Optional[str] + """The postal code of the address.""" + + state: Optional[str] + """The state of the address.""" + + tax_id_type: Optional[TaxIdentifierType] + """The type of tax identifier""" + + tax_id_value: Optional[str] + """The value of the tax identifier.""" + + +class CreateInvoiceInputWithProductIDAndEmailAddressLineItem(TypedDict, total=False): + """ + A single line item to include on the invoice, with a label, quantity, and unit price. + """ + + label: Required[str] + """The label or description for this line item.""" + + unit_price: Required[float] + """The unit price for this line item. + + Provided as a number in the specified currency. Eg: 10.43 for $10.43 + """ + + quantity: Optional[float] + """The quantity of this line item. Defaults to 1.""" + + InvoiceCreateParams: TypeAlias = Union[ CreateInvoiceInputWithProductAndMemberID, CreateInvoiceInputWithProductAndEmailAddress, diff --git a/src/whop_sdk/types/invoice_mark_paid_response.py b/src/whop_sdk/types/invoice_mark_paid_response.py new file mode 100644 index 0000000..4ea337e --- /dev/null +++ b/src/whop_sdk/types/invoice_mark_paid_response.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import TypeAlias + +__all__ = ["InvoiceMarkPaidResponse"] + +InvoiceMarkPaidResponse: TypeAlias = bool diff --git a/src/whop_sdk/types/invoice_mark_uncollectible_response.py b/src/whop_sdk/types/invoice_mark_uncollectible_response.py new file mode 100644 index 0000000..a34c66d --- /dev/null +++ b/src/whop_sdk/types/invoice_mark_uncollectible_response.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import TypeAlias + +__all__ = ["InvoiceMarkUncollectibleResponse"] + +InvoiceMarkUncollectibleResponse: TypeAlias = bool diff --git a/src/whop_sdk/types/invoice_marked_uncollectible_webhook_event.py b/src/whop_sdk/types/invoice_marked_uncollectible_webhook_event.py new file mode 100644 index 0000000..3152d5d --- /dev/null +++ b/src/whop_sdk/types/invoice_marked_uncollectible_webhook_event.py @@ -0,0 +1,34 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.invoice import Invoice + +__all__ = ["InvoiceMarkedUncollectibleWebhookEvent"] + + +class InvoiceMarkedUncollectibleWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Invoice + """ + An invoice represents an itemized bill sent by a company to a customer for a + specific product and plan, tracking the amount owed, due date, and payment + status. + """ + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["invoice.marked_uncollectible"] + """The webhook event type""" + + company_id: Optional[str] = None + """The company ID that this webhook event is associated with""" diff --git a/src/whop_sdk/types/payment_create_params.py b/src/whop_sdk/types/payment_create_params.py index 2d03e3b..3335e5f 100644 --- a/src/whop_sdk/types/payment_create_params.py +++ b/src/whop_sdk/types/payment_create_params.py @@ -97,6 +97,14 @@ class CreatePaymentInputWithPlanPlan(TypedDict, total=False): currency: Required[Currency] """The respective currency identifier for the plan.""" + application_fee_amount: Optional[float] + """The application fee amount collected by the platform from this connected + account. + + Provided as a number in dollars (e.g., 5.00 for $5.00). Must be less than the + total payment amount. Only valid for connected accounts with a parent company. + """ + billing_period: Optional[int] """The interval in days at which the plan charges (renewal plans). diff --git a/src/whop_sdk/types/payment_list_params.py b/src/whop_sdk/types/payment_list_params.py index 5af6fe5..1fcc2a2 100644 --- a/src/whop_sdk/types/payment_list_params.py +++ b/src/whop_sdk/types/payment_list_params.py @@ -74,3 +74,9 @@ class PaymentListParams(TypedDict, total=False): substatuses: Optional[List[FriendlyReceiptStatus]] """Filter payments by their current substatus for more granular filtering.""" + + updated_after: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """Only return payments last updated after this timestamp.""" + + updated_before: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """Only return payments last updated before this timestamp.""" diff --git a/src/whop_sdk/types/payment_list_response.py b/src/whop_sdk/types/payment_list_response.py index 438f5ec..e026626 100644 --- a/src/whop_sdk/types/payment_list_response.py +++ b/src/whop_sdk/types/payment_list_response.py @@ -348,6 +348,9 @@ class PaymentListResponse(BaseModel): total: Optional[float] = None """The total to show to the creator (excluding buyer fees).""" + updated_at: datetime + """The datetime the payment was last updated.""" + usd_total: Optional[float] = None """The total in USD to show to the creator (excluding buyer fees).""" diff --git a/src/whop_sdk/types/payment_method_types.py b/src/whop_sdk/types/payment_method_types.py index c61cc63..526c34f 100644 --- a/src/whop_sdk/types/payment_method_types.py +++ b/src/whop_sdk/types/payment_method_types.py @@ -94,5 +94,6 @@ "vipps", "wechat_pay", "zip", + "coinflow", "unknown", ] diff --git a/src/whop_sdk/types/payment_provider.py b/src/whop_sdk/types/payment_provider.py index c2ba590..6d8567f 100644 --- a/src/whop_sdk/types/payment_provider.py +++ b/src/whop_sdk/types/payment_provider.py @@ -17,4 +17,6 @@ "claritypay", "checkout_dot_com", "airwallex", + "coinflow", + "sequra", ] diff --git a/src/whop_sdk/types/plan_create_params.py b/src/whop_sdk/types/plan_create_params.py index 5fd63de..aebe213 100644 --- a/src/whop_sdk/types/plan_create_params.py +++ b/src/whop_sdk/types/plan_create_params.py @@ -12,7 +12,7 @@ from .payment_method_types import PaymentMethodTypes from .shared.release_method import ReleaseMethod -__all__ = ["PlanCreateParams", "CustomField", "Image", "PaymentMethodConfiguration"] +__all__ = ["PlanCreateParams", "CheckoutStyling", "CustomField", "Image", "PaymentMethodConfiguration"] class PlanCreateParams(TypedDict, total=False): @@ -28,6 +28,12 @@ class PlanCreateParams(TypedDict, total=False): For example, 30 for monthly or 365 for yearly. """ + checkout_styling: Optional[CheckoutStyling] + """Checkout styling overrides for this plan. + + Pass null to inherit from the company default. + """ + currency: Optional[Currency] """The available currencies on the platform""" @@ -109,6 +115,22 @@ class PlanCreateParams(TypedDict, total=False): """Visibility of a resource""" +class CheckoutStyling(TypedDict, total=False): + """Checkout styling overrides for this plan. + + Pass null to inherit from the company default. + """ + + border_style: Optional[Literal["rounded", "pill", "rectangular"]] + """The different border-radius styles available for checkout pages.""" + + button_color: Optional[str] + """A hex color code for the button color (e.g. #FF5733).""" + + font_family: Optional[Literal["system", "roboto", "open_sans"]] + """The different font families available for checkout pages.""" + + class CustomField(TypedDict, total=False): field_type: Required[Literal["text"]] """The type of the custom field.""" diff --git a/src/whop_sdk/types/plan_update_params.py b/src/whop_sdk/types/plan_update_params.py index 6750817..d98f100 100644 --- a/src/whop_sdk/types/plan_update_params.py +++ b/src/whop_sdk/types/plan_update_params.py @@ -10,7 +10,7 @@ from .shared.visibility import Visibility from .payment_method_types import PaymentMethodTypes -__all__ = ["PlanUpdateParams", "CustomField", "Image", "PaymentMethodConfiguration"] +__all__ = ["PlanUpdateParams", "CheckoutStyling", "CustomField", "Image", "PaymentMethodConfiguration"] class PlanUpdateParams(TypedDict, total=False): @@ -20,6 +20,12 @@ class PlanUpdateParams(TypedDict, total=False): For example, 30 for monthly or 365 for yearly. """ + checkout_styling: Optional[CheckoutStyling] + """Checkout styling overrides for this plan. + + Pass null to remove all overrides and inherit from the company default. + """ + currency: Optional[Currency] """The available currencies on the platform""" @@ -102,6 +108,22 @@ class PlanUpdateParams(TypedDict, total=False): """Visibility of a resource""" +class CheckoutStyling(TypedDict, total=False): + """Checkout styling overrides for this plan. + + Pass null to remove all overrides and inherit from the company default. + """ + + border_style: Optional[Literal["rounded", "pill", "rectangular"]] + """The different border-radius styles available for checkout pages.""" + + button_color: Optional[str] + """A hex color code for the button color (e.g. #FF5733).""" + + font_family: Optional[Literal["system", "roboto", "open_sans"]] + """The different font families available for checkout pages.""" + + class CustomField(TypedDict, total=False): field_type: Required[Literal["text"]] """The type of the custom field.""" diff --git a/src/whop_sdk/types/product_create_params.py b/src/whop_sdk/types/product_create_params.py index ea86cc0..ed4c851 100644 --- a/src/whop_sdk/types/product_create_params.py +++ b/src/whop_sdk/types/product_create_params.py @@ -21,7 +21,7 @@ class ProductCreateParams(TypedDict, total=False): """The unique identifier of the company to create this product for.""" title: Required[str] - """The display name of the product. Maximum 40 characters.""" + """The display name of the product. Maximum 80 characters.""" collect_shipping_address: Optional[bool] """Whether the checkout flow collects a shipping address from the customer.""" diff --git a/src/whop_sdk/types/product_update_params.py b/src/whop_sdk/types/product_update_params.py index d7e9dca..6082edf 100644 --- a/src/whop_sdk/types/product_update_params.py +++ b/src/whop_sdk/types/product_update_params.py @@ -78,7 +78,7 @@ class ProductUpdateParams(TypedDict, total=False): """Layout and display configuration for this product on the company's store page.""" title: Optional[str] - """The display name of the product. Maximum 40 characters.""" + """The display name of the product. Maximum 80 characters.""" visibility: Optional[Visibility] """Visibility of a resource""" diff --git a/src/whop_sdk/types/resolution_center_case_created_webhook_event.py b/src/whop_sdk/types/resolution_center_case_created_webhook_event.py new file mode 100644 index 0000000..ef32678 --- /dev/null +++ b/src/whop_sdk/types/resolution_center_case_created_webhook_event.py @@ -0,0 +1,221 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.currency import Currency +from .resolution_center_case_status import ResolutionCenterCaseStatus +from .resolution_center_case_issue_type import ResolutionCenterCaseIssueType +from .resolution_center_case_customer_response import ResolutionCenterCaseCustomerResponse +from .resolution_center_case_merchant_response import ResolutionCenterCaseMerchantResponse +from .resolution_center_case_platform_response import ResolutionCenterCasePlatformResponse + +__all__ = [ + "ResolutionCenterCaseCreatedWebhookEvent", + "Data", + "DataCompany", + "DataMember", + "DataPayment", + "DataResolutionEvent", + "DataUser", +] + + +class DataCompany(BaseModel): + """The company involved in this resolution case. + + Null if the company no longer exists. + """ + + id: str + """The unique identifier for the company.""" + + title: str + """The display name of the company shown to customers.""" + + +class DataMember(BaseModel): + """The membership record associated with the disputed payment. + + Null if the membership no longer exists. + """ + + id: str + """The unique identifier for the extra public member.""" + + +class DataPayment(BaseModel): + """The payment record that is the subject of this resolution case.""" + + id: str + """The unique identifier for the payment.""" + + created_at: datetime + """The datetime the payment was created.""" + + currency: Optional[Currency] = None + """The available currencies on the platform""" + + paid_at: Optional[datetime] = None + """The time at which this payment was successfully collected. + + Null if the payment has not yet succeeded. As a Unix timestamp. + """ + + subtotal: Optional[float] = None + """The payment amount before taxes and discounts are applied. + + In the currency specified by the currency field. + """ + + total: float + """ + The total amount charged to the customer for this payment, including taxes and + after any discounts. In the currency specified by the currency field. + """ + + +class DataResolutionEvent(BaseModel): + """ + A resolution event is a message or action within a resolution case, such as a response, escalation, or status change. + """ + + id: str + """The unique identifier for the resolution event.""" + + action: Literal[ + "created", + "responded", + "accepted", + "denied", + "appealed", + "withdrew", + "requested_more_info", + "escalated", + "dispute_opened", + "dispute_customer_won", + "dispute_merchant_won", + ] + """The type of action recorded in this event.""" + + created_at: datetime + """The datetime the resolution event was created.""" + + details: Optional[str] = None + """The message body or additional context provided with this resolution event. + + Null if no details were included. + """ + + reporter_type: Literal["merchant", "customer", "platform", "system"] + """The party who performed this action.""" + + +class DataUser(BaseModel): + """The customer (buyer) who filed this resolution case.""" + + 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 Data(BaseModel): + """ + A resolution center case is a dispute or support case between a user and a company, tracking the issue, status, and outcome. + """ + + id: str + """The unique identifier for the resolution.""" + + company: Optional[DataCompany] = None + """The company involved in this resolution case. + + Null if the company no longer exists. + """ + + created_at: datetime + """The datetime the resolution was created.""" + + customer_appealed: bool + """Whether the customer has filed an appeal after the initial resolution decision.""" + + customer_response_actions: List[ResolutionCenterCaseCustomerResponse] + """The list of actions currently available to the customer.""" + + due_date: Optional[datetime] = None + """The deadline by which the next response is required. + + Null if no deadline is currently active. As a Unix timestamp. + """ + + issue: ResolutionCenterCaseIssueType + """The category of the dispute.""" + + member: Optional[DataMember] = None + """The membership record associated with the disputed payment. + + Null if the membership no longer exists. + """ + + merchant_appealed: bool + """Whether the merchant has filed an appeal after the initial resolution decision.""" + + merchant_response_actions: List[ResolutionCenterCaseMerchantResponse] + """The list of actions currently available to the merchant.""" + + payment: DataPayment + """The payment record that is the subject of this resolution case.""" + + platform_response_actions: List[ResolutionCenterCasePlatformResponse] + """ + The list of actions currently available to the Whop platform for moderating this + resolution. + """ + + resolution_events: List[DataResolutionEvent] + """ + The most recent 50 messages, actions, and status changes that have occurred + during this resolution case. + """ + + status: ResolutionCenterCaseStatus + """ + The current status of the resolution case, indicating which party needs to + respond or if the case is closed. + """ + + updated_at: datetime + """The datetime the resolution was last updated.""" + + user: DataUser + """The customer (buyer) who filed this resolution case.""" + + +class ResolutionCenterCaseCreatedWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Data + """ + A resolution center case is a dispute or support case between a user and a + company, tracking the issue, status, and outcome. + """ + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["resolution_center_case.created"] + """The webhook event type""" + + company_id: Optional[str] = None + """The company ID that this webhook event is associated with""" diff --git a/src/whop_sdk/types/resolution_center_case_decided_webhook_event.py b/src/whop_sdk/types/resolution_center_case_decided_webhook_event.py new file mode 100644 index 0000000..c4641db --- /dev/null +++ b/src/whop_sdk/types/resolution_center_case_decided_webhook_event.py @@ -0,0 +1,221 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.currency import Currency +from .resolution_center_case_status import ResolutionCenterCaseStatus +from .resolution_center_case_issue_type import ResolutionCenterCaseIssueType +from .resolution_center_case_customer_response import ResolutionCenterCaseCustomerResponse +from .resolution_center_case_merchant_response import ResolutionCenterCaseMerchantResponse +from .resolution_center_case_platform_response import ResolutionCenterCasePlatformResponse + +__all__ = [ + "ResolutionCenterCaseDecidedWebhookEvent", + "Data", + "DataCompany", + "DataMember", + "DataPayment", + "DataResolutionEvent", + "DataUser", +] + + +class DataCompany(BaseModel): + """The company involved in this resolution case. + + Null if the company no longer exists. + """ + + id: str + """The unique identifier for the company.""" + + title: str + """The display name of the company shown to customers.""" + + +class DataMember(BaseModel): + """The membership record associated with the disputed payment. + + Null if the membership no longer exists. + """ + + id: str + """The unique identifier for the extra public member.""" + + +class DataPayment(BaseModel): + """The payment record that is the subject of this resolution case.""" + + id: str + """The unique identifier for the payment.""" + + created_at: datetime + """The datetime the payment was created.""" + + currency: Optional[Currency] = None + """The available currencies on the platform""" + + paid_at: Optional[datetime] = None + """The time at which this payment was successfully collected. + + Null if the payment has not yet succeeded. As a Unix timestamp. + """ + + subtotal: Optional[float] = None + """The payment amount before taxes and discounts are applied. + + In the currency specified by the currency field. + """ + + total: float + """ + The total amount charged to the customer for this payment, including taxes and + after any discounts. In the currency specified by the currency field. + """ + + +class DataResolutionEvent(BaseModel): + """ + A resolution event is a message or action within a resolution case, such as a response, escalation, or status change. + """ + + id: str + """The unique identifier for the resolution event.""" + + action: Literal[ + "created", + "responded", + "accepted", + "denied", + "appealed", + "withdrew", + "requested_more_info", + "escalated", + "dispute_opened", + "dispute_customer_won", + "dispute_merchant_won", + ] + """The type of action recorded in this event.""" + + created_at: datetime + """The datetime the resolution event was created.""" + + details: Optional[str] = None + """The message body or additional context provided with this resolution event. + + Null if no details were included. + """ + + reporter_type: Literal["merchant", "customer", "platform", "system"] + """The party who performed this action.""" + + +class DataUser(BaseModel): + """The customer (buyer) who filed this resolution case.""" + + 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 Data(BaseModel): + """ + A resolution center case is a dispute or support case between a user and a company, tracking the issue, status, and outcome. + """ + + id: str + """The unique identifier for the resolution.""" + + company: Optional[DataCompany] = None + """The company involved in this resolution case. + + Null if the company no longer exists. + """ + + created_at: datetime + """The datetime the resolution was created.""" + + customer_appealed: bool + """Whether the customer has filed an appeal after the initial resolution decision.""" + + customer_response_actions: List[ResolutionCenterCaseCustomerResponse] + """The list of actions currently available to the customer.""" + + due_date: Optional[datetime] = None + """The deadline by which the next response is required. + + Null if no deadline is currently active. As a Unix timestamp. + """ + + issue: ResolutionCenterCaseIssueType + """The category of the dispute.""" + + member: Optional[DataMember] = None + """The membership record associated with the disputed payment. + + Null if the membership no longer exists. + """ + + merchant_appealed: bool + """Whether the merchant has filed an appeal after the initial resolution decision.""" + + merchant_response_actions: List[ResolutionCenterCaseMerchantResponse] + """The list of actions currently available to the merchant.""" + + payment: DataPayment + """The payment record that is the subject of this resolution case.""" + + platform_response_actions: List[ResolutionCenterCasePlatformResponse] + """ + The list of actions currently available to the Whop platform for moderating this + resolution. + """ + + resolution_events: List[DataResolutionEvent] + """ + The most recent 50 messages, actions, and status changes that have occurred + during this resolution case. + """ + + status: ResolutionCenterCaseStatus + """ + The current status of the resolution case, indicating which party needs to + respond or if the case is closed. + """ + + updated_at: datetime + """The datetime the resolution was last updated.""" + + user: DataUser + """The customer (buyer) who filed this resolution case.""" + + +class ResolutionCenterCaseDecidedWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Data + """ + A resolution center case is a dispute or support case between a user and a + company, tracking the issue, status, and outcome. + """ + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["resolution_center_case.decided"] + """The webhook event type""" + + company_id: Optional[str] = None + """The company ID that this webhook event is associated with""" diff --git a/src/whop_sdk/types/resolution_center_case_updated_webhook_event.py b/src/whop_sdk/types/resolution_center_case_updated_webhook_event.py new file mode 100644 index 0000000..349256f --- /dev/null +++ b/src/whop_sdk/types/resolution_center_case_updated_webhook_event.py @@ -0,0 +1,221 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.currency import Currency +from .resolution_center_case_status import ResolutionCenterCaseStatus +from .resolution_center_case_issue_type import ResolutionCenterCaseIssueType +from .resolution_center_case_customer_response import ResolutionCenterCaseCustomerResponse +from .resolution_center_case_merchant_response import ResolutionCenterCaseMerchantResponse +from .resolution_center_case_platform_response import ResolutionCenterCasePlatformResponse + +__all__ = [ + "ResolutionCenterCaseUpdatedWebhookEvent", + "Data", + "DataCompany", + "DataMember", + "DataPayment", + "DataResolutionEvent", + "DataUser", +] + + +class DataCompany(BaseModel): + """The company involved in this resolution case. + + Null if the company no longer exists. + """ + + id: str + """The unique identifier for the company.""" + + title: str + """The display name of the company shown to customers.""" + + +class DataMember(BaseModel): + """The membership record associated with the disputed payment. + + Null if the membership no longer exists. + """ + + id: str + """The unique identifier for the extra public member.""" + + +class DataPayment(BaseModel): + """The payment record that is the subject of this resolution case.""" + + id: str + """The unique identifier for the payment.""" + + created_at: datetime + """The datetime the payment was created.""" + + currency: Optional[Currency] = None + """The available currencies on the platform""" + + paid_at: Optional[datetime] = None + """The time at which this payment was successfully collected. + + Null if the payment has not yet succeeded. As a Unix timestamp. + """ + + subtotal: Optional[float] = None + """The payment amount before taxes and discounts are applied. + + In the currency specified by the currency field. + """ + + total: float + """ + The total amount charged to the customer for this payment, including taxes and + after any discounts. In the currency specified by the currency field. + """ + + +class DataResolutionEvent(BaseModel): + """ + A resolution event is a message or action within a resolution case, such as a response, escalation, or status change. + """ + + id: str + """The unique identifier for the resolution event.""" + + action: Literal[ + "created", + "responded", + "accepted", + "denied", + "appealed", + "withdrew", + "requested_more_info", + "escalated", + "dispute_opened", + "dispute_customer_won", + "dispute_merchant_won", + ] + """The type of action recorded in this event.""" + + created_at: datetime + """The datetime the resolution event was created.""" + + details: Optional[str] = None + """The message body or additional context provided with this resolution event. + + Null if no details were included. + """ + + reporter_type: Literal["merchant", "customer", "platform", "system"] + """The party who performed this action.""" + + +class DataUser(BaseModel): + """The customer (buyer) who filed this resolution case.""" + + 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 Data(BaseModel): + """ + A resolution center case is a dispute or support case between a user and a company, tracking the issue, status, and outcome. + """ + + id: str + """The unique identifier for the resolution.""" + + company: Optional[DataCompany] = None + """The company involved in this resolution case. + + Null if the company no longer exists. + """ + + created_at: datetime + """The datetime the resolution was created.""" + + customer_appealed: bool + """Whether the customer has filed an appeal after the initial resolution decision.""" + + customer_response_actions: List[ResolutionCenterCaseCustomerResponse] + """The list of actions currently available to the customer.""" + + due_date: Optional[datetime] = None + """The deadline by which the next response is required. + + Null if no deadline is currently active. As a Unix timestamp. + """ + + issue: ResolutionCenterCaseIssueType + """The category of the dispute.""" + + member: Optional[DataMember] = None + """The membership record associated with the disputed payment. + + Null if the membership no longer exists. + """ + + merchant_appealed: bool + """Whether the merchant has filed an appeal after the initial resolution decision.""" + + merchant_response_actions: List[ResolutionCenterCaseMerchantResponse] + """The list of actions currently available to the merchant.""" + + payment: DataPayment + """The payment record that is the subject of this resolution case.""" + + platform_response_actions: List[ResolutionCenterCasePlatformResponse] + """ + The list of actions currently available to the Whop platform for moderating this + resolution. + """ + + resolution_events: List[DataResolutionEvent] + """ + The most recent 50 messages, actions, and status changes that have occurred + during this resolution case. + """ + + status: ResolutionCenterCaseStatus + """ + The current status of the resolution case, indicating which party needs to + respond or if the case is closed. + """ + + updated_at: datetime + """The datetime the resolution was last updated.""" + + user: DataUser + """The customer (buyer) who filed this resolution case.""" + + +class ResolutionCenterCaseUpdatedWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Data + """ + A resolution center case is a dispute or support case between a user and a + company, tracking the issue, status, and outcome. + """ + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["resolution_center_case.updated"] + """The webhook event type""" + + company_id: Optional[str] = None + """The company ID that this webhook event is associated with""" diff --git a/src/whop_sdk/types/shared/app.py b/src/whop_sdk/types/shared/app.py index ad75be7..9082899 100644 --- a/src/whop_sdk/types/shared/app.py +++ b/src/whop_sdk/types/shared/app.py @@ -205,6 +205,19 @@ class App(BaseModel): Maximum 30 characters. """ + openapi_path: Optional[str] = None + """ + The URL path template for a specific view of this app, appended to the base + domain (e.g., '/experiences/[experienceId]'). Null if the specified view type is + not configured. + """ + + origin: Optional[str] = None + """ + The full origin URL for this app's proxied domain (e.g., + 'https://myapp.apps.whop.com'). Null if no proxy domain is configured. + """ + redirect_uris: List[str] """ The whitelisted OAuth callback URLs that users are redirected to after @@ -217,6 +230,13 @@ class App(BaseModel): required and optional permissions with justifications. """ + skills_path: Optional[str] = None + """ + The URL path template for a specific view of this app, appended to the base + domain (e.g., '/experiences/[experienceId]'). Null if the specified view type is + not configured. + """ + stats: Optional[Stats] = None """ Aggregate usage statistics for this app, including daily, weekly, and monthly diff --git a/src/whop_sdk/types/shared/app_view_type.py b/src/whop_sdk/types/shared/app_view_type.py index 6665d5b..05a0086 100644 --- a/src/whop_sdk/types/shared/app_view_type.py +++ b/src/whop_sdk/types/shared/app_view_type.py @@ -4,4 +4,4 @@ __all__ = ["AppViewType"] -AppViewType: TypeAlias = Literal["hub", "discover", "dash", "dashboard", "analytics"] +AppViewType: TypeAlias = Literal["hub", "discover", "dash", "dashboard", "analytics", "skills", "openapi"] diff --git a/src/whop_sdk/types/shared/company.py b/src/whop_sdk/types/shared/company.py index e30b8c1..5155b67 100644 --- a/src/whop_sdk/types/shared/company.py +++ b/src/whop_sdk/types/shared/company.py @@ -6,7 +6,20 @@ from ..._models import BaseModel -__all__ = ["Company", "Logo", "OwnerUser", "SocialLink"] +__all__ = ["Company", "FeaturedAffiliateProduct", "Logo", "OwnerUser", "SocialLink"] + + +class FeaturedAffiliateProduct(BaseModel): + """The product featured for affiliates to promote on this company's affiliate page. + + Null if none is configured. + """ + + id: str + """The unique identifier for the product.""" + + name: str + """The display name of the product shown to customers. Maximum 50 characters.""" class Logo(BaseModel): @@ -54,6 +67,12 @@ class Company(BaseModel): id: str """The unique identifier for the company.""" + affiliate_instructions: Optional[str] = None + """ + Guidelines and instructions provided to affiliates explaining how to promote + this company's products. + """ + created_at: datetime """The datetime the company was created.""" @@ -63,6 +82,12 @@ class Company(BaseModel): customers on the store page. """ + featured_affiliate_product: Optional[FeaturedAffiliateProduct] = None + """The product featured for affiliates to promote on this company's affiliate page. + + Null if none is configured. + """ + logo: Optional[Logo] = None """The company's logo.""" @@ -104,6 +129,9 @@ class Company(BaseModel): company. """ + target_audience: Optional[str] = None + """The target audience for the company. Null if not set.""" + title: str """The display name of the company shown to customers.""" diff --git a/src/whop_sdk/types/shared/invoice_status.py b/src/whop_sdk/types/shared/invoice_status.py index 255b6a7..7e48fb6 100644 --- a/src/whop_sdk/types/shared/invoice_status.py +++ b/src/whop_sdk/types/shared/invoice_status.py @@ -4,4 +4,4 @@ __all__ = ["InvoiceStatus"] -InvoiceStatus: TypeAlias = Literal["draft", "open", "paid", "past_due", "void"] +InvoiceStatus: TypeAlias = Literal["draft", "open", "paid", "past_due", "uncollectible", "void"] diff --git a/src/whop_sdk/types/shared/payment.py b/src/whop_sdk/types/shared/payment.py index 009f035..4d92b9e 100644 --- a/src/whop_sdk/types/shared/payment.py +++ b/src/whop_sdk/types/shared/payment.py @@ -154,7 +154,17 @@ class FinancingTransaction(BaseModel): """The date and time the payment transaction was created.""" status: Literal[ - "succeeded", "declined", "error", "pending", "created", "expired", "won", "rejected", "lost", "prevented" + "succeeded", + "declined", + "error", + "pending", + "created", + "expired", + "won", + "rejected", + "lost", + "prevented", + "canceled", ] """The status of the payment transaction.""" @@ -163,7 +173,7 @@ class FinancingTransaction(BaseModel): "authorize", "capture", "refund", - "cancel", + "canceled", "verify", "chargeback", "pre_chargeback", @@ -501,6 +511,9 @@ class Payment(BaseModel): total: Optional[float] = None """The total to show to the creator (excluding buyer fees).""" + updated_at: datetime + """The datetime the payment was last updated.""" + usd_total: Optional[float] = None """The total in USD to show to the creator (excluding buyer fees).""" diff --git a/src/whop_sdk/types/shared_params/app_view_type.py b/src/whop_sdk/types/shared_params/app_view_type.py index 65c818f..2b60454 100644 --- a/src/whop_sdk/types/shared_params/app_view_type.py +++ b/src/whop_sdk/types/shared_params/app_view_type.py @@ -6,4 +6,4 @@ __all__ = ["AppViewType"] -AppViewType: TypeAlias = Literal["hub", "discover", "dash", "dashboard", "analytics"] +AppViewType: TypeAlias = Literal["hub", "discover", "dash", "dashboard", "analytics", "skills", "openapi"] diff --git a/src/whop_sdk/types/shared_params/invoice_status.py b/src/whop_sdk/types/shared_params/invoice_status.py index 1006ba8..906e062 100644 --- a/src/whop_sdk/types/shared_params/invoice_status.py +++ b/src/whop_sdk/types/shared_params/invoice_status.py @@ -6,4 +6,4 @@ __all__ = ["InvoiceStatus"] -InvoiceStatus: TypeAlias = Literal["draft", "open", "paid", "past_due", "void"] +InvoiceStatus: TypeAlias = Literal["draft", "open", "paid", "past_due", "uncollectible", "void"] diff --git a/src/whop_sdk/types/tax_identifier_type.py b/src/whop_sdk/types/tax_identifier_type.py new file mode 100644 index 0000000..6b186a3 --- /dev/null +++ b/src/whop_sdk/types/tax_identifier_type.py @@ -0,0 +1,119 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["TaxIdentifierType"] + +TaxIdentifierType: TypeAlias = Literal[ + "ad_nrt", + "ao_tin", + "ar_cuit", + "am_tin", + "aw_tin", + "au_abn", + "au_arn", + "eu_vat", + "az_tin", + "bs_tin", + "bh_vat", + "bd_bin", + "bb_tin", + "by_tin", + "bj_ifu", + "bo_tin", + "ba_tin", + "br_cnpj", + "br_cpf", + "bg_uic", + "bf_ifu", + "kh_tin", + "cm_niu", + "ca_bn", + "ca_gst_hst", + "ca_pst_bc", + "ca_pst_mb", + "ca_pst_sk", + "ca_qst", + "cv_nif", + "cl_tin", + "cn_tin", + "co_nit", + "cd_nif", + "cr_tin", + "hr_oib", + "do_rcn", + "ec_ruc", + "eg_tin", + "sv_nit", + "et_tin", + "eu_oss_vat", + "ge_vat", + "de_stn", + "gb_vat", + "gn_nif", + "hk_br", + "hu_tin", + "is_vat", + "in_gst", + "id_npwp", + "il_vat", + "jp_cn", + "jp_rn", + "jp_trn", + "kz_bin", + "ke_pin", + "kg_tin", + "la_tin", + "li_uid", + "li_vat", + "my_frp", + "my_itn", + "my_sst", + "mr_nif", + "mx_rfc", + "md_vat", + "me_pib", + "ma_vat", + "np_pan", + "nz_gst", + "ng_tin", + "mk_vat", + "no_vat", + "no_voec", + "om_vat", + "pe_ruc", + "ph_tin", + "pl_nip", + "ro_tin", + "ru_inn", + "ru_kpp", + "sa_vat", + "sn_ninea", + "rs_pib", + "sg_gst", + "sg_uen", + "si_tin", + "za_vat", + "kr_brn", + "es_cif", + "ch_uid", + "ch_vat", + "tw_vat", + "tj_tin", + "tz_vat", + "th_vat", + "tr_tin", + "ug_tin", + "ua_vat", + "ae_trn", + "us_ein", + "uy_ruc", + "uz_tin", + "uz_vat", + "ve_rif", + "vn_tin", + "zm_tin", + "zw_tin", + "sr_fin", + "xi_vat", +] diff --git a/src/whop_sdk/types/unwrap_webhook_event.py b/src/whop_sdk/types/unwrap_webhook_event.py index 78041be..96f1582 100644 --- a/src/whop_sdk/types/unwrap_webhook_event.py +++ b/src/whop_sdk/types/unwrap_webhook_event.py @@ -29,8 +29,12 @@ from .membership_deactivated_webhook_event import MembershipDeactivatedWebhookEvent from .setup_intent_succeeded_webhook_event import SetupIntentSucceededWebhookEvent from .verification_succeeded_webhook_event import VerificationSucceededWebhookEvent +from .invoice_marked_uncollectible_webhook_event import InvoiceMarkedUncollectibleWebhookEvent from .setup_intent_requires_action_webhook_event import SetupIntentRequiresActionWebhookEvent from .payout_account_status_updated_webhook_event import PayoutAccountStatusUpdatedWebhookEvent +from .resolution_center_case_created_webhook_event import ResolutionCenterCaseCreatedWebhookEvent +from .resolution_center_case_decided_webhook_event import ResolutionCenterCaseDecidedWebhookEvent +from .resolution_center_case_updated_webhook_event import ResolutionCenterCaseUpdatedWebhookEvent from .course_lesson_interaction_completed_webhook_event import CourseLessonInteractionCompletedWebhookEvent from .membership_cancel_at_period_end_changed_webhook_event import MembershipCancelAtPeriodEndChangedWebhookEvent @@ -39,6 +43,7 @@ UnwrapWebhookEvent: TypeAlias = Annotated[ Union[ InvoiceCreatedWebhookEvent, + InvoiceMarkedUncollectibleWebhookEvent, InvoicePaidWebhookEvent, InvoicePastDueWebhookEvent, InvoiceVoidedWebhookEvent, @@ -57,6 +62,9 @@ PayoutMethodCreatedWebhookEvent, VerificationSucceededWebhookEvent, PayoutAccountStatusUpdatedWebhookEvent, + ResolutionCenterCaseCreatedWebhookEvent, + ResolutionCenterCaseUpdatedWebhookEvent, + ResolutionCenterCaseDecidedWebhookEvent, PaymentCreatedWebhookEvent, PaymentSucceededWebhookEvent, PaymentFailedWebhookEvent, diff --git a/src/whop_sdk/types/webhook_event.py b/src/whop_sdk/types/webhook_event.py index e2a5415..174e660 100644 --- a/src/whop_sdk/types/webhook_event.py +++ b/src/whop_sdk/types/webhook_event.py @@ -6,6 +6,7 @@ WebhookEvent: TypeAlias = Literal[ "invoice.created", + "invoice.marked_uncollectible", "invoice.paid", "invoice.past_due", "invoice.voided", @@ -24,6 +25,9 @@ "payout_method.created", "verification.succeeded", "payout_account.status_updated", + "resolution_center_case.created", + "resolution_center_case.updated", + "resolution_center_case.decided", "payment.created", "payment.succeeded", "payment.failed", diff --git a/tests/api_resources/test_apps.py b/tests/api_resources/test_apps.py index 1eb7bce..042e705 100644 --- a/tests/api_resources/test_apps.py +++ b/tests/api_resources/test_apps.py @@ -133,8 +133,10 @@ def test_method_update_with_all_params(self, client: Whop) -> None: icon={"id": "id"}, name="name", oauth_client_type="public", + openapi_path="openapi_path", redirect_uris=["string"], required_scopes=["read_user"], + skills_path="skills_path", status="live", ) assert_matches_type(App, app, path=["response"]) @@ -339,8 +341,10 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N icon={"id": "id"}, name="name", oauth_client_type="public", + openapi_path="openapi_path", redirect_uris=["string"], required_scopes=["read_user"], + skills_path="skills_path", status="live", ) assert_matches_type(App, app, path=["response"]) diff --git a/tests/api_resources/test_checkout_configurations.py b/tests/api_resources/test_checkout_configurations.py index 8345d28..cb45542 100644 --- a/tests/api_resources/test_checkout_configurations.py +++ b/tests/api_resources/test_checkout_configurations.py @@ -89,6 +89,11 @@ def test_method_create_with_all_params_overload_1(self, client: Whop) -> None: "visibility": "visible", }, affiliate_code="affiliate_code", + checkout_styling={ + "border_style": "rounded", + "button_color": "button_color", + "font_family": "system", + }, currency="usd", metadata={"foo": "bar"}, mode="payment", @@ -148,6 +153,11 @@ def test_method_create_with_all_params_overload_2(self, client: Whop) -> None: checkout_configuration = client.checkout_configurations.create( plan_id="plan_xxxxxxxxxxxxx", affiliate_code="affiliate_code", + checkout_styling={ + "border_style": "rounded", + "button_color": "button_color", + "font_family": "system", + }, currency="usd", metadata={"foo": "bar"}, mode="payment", @@ -202,6 +212,11 @@ def test_method_create_with_all_params_overload_3(self, client: Whop) -> None: checkout_configuration = client.checkout_configurations.create( company_id="biz_xxxxxxxxxxxxxx", mode="setup", + checkout_styling={ + "border_style": "rounded", + "button_color": "button_color", + "font_family": "system", + }, currency="usd", metadata={"foo": "bar"}, payment_method_configuration={ @@ -415,6 +430,11 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn "visibility": "visible", }, affiliate_code="affiliate_code", + checkout_styling={ + "border_style": "rounded", + "button_color": "button_color", + "font_family": "system", + }, currency="usd", metadata={"foo": "bar"}, mode="payment", @@ -474,6 +494,11 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn checkout_configuration = await async_client.checkout_configurations.create( plan_id="plan_xxxxxxxxxxxxx", affiliate_code="affiliate_code", + checkout_styling={ + "border_style": "rounded", + "button_color": "button_color", + "font_family": "system", + }, currency="usd", metadata={"foo": "bar"}, mode="payment", @@ -528,6 +553,11 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn checkout_configuration = await async_client.checkout_configurations.create( company_id="biz_xxxxxxxxxxxxxx", mode="setup", + checkout_styling={ + "border_style": "rounded", + "button_color": "button_color", + "font_family": "system", + }, currency="usd", metadata={"foo": "bar"}, payment_method_configuration={ diff --git a/tests/api_resources/test_companies.py b/tests/api_resources/test_companies.py index 30eb5eb..8b3e6f8 100644 --- a/tests/api_resources/test_companies.py +++ b/tests/api_resources/test_companies.py @@ -125,8 +125,11 @@ def test_method_update(self, client: Whop) -> None: def test_method_update_with_all_params(self, client: Whop) -> None: company = client.companies.update( id="biz_xxxxxxxxxxxxxx", + affiliate_application_required=True, + affiliate_instructions="affiliate_instructions", banner_image={"id": "id"}, description="description", + featured_affiliate_product_id="featured_affiliate_product_id", logo={"id": "id"}, route="route", send_customer_emails=True, @@ -321,8 +324,11 @@ async def test_method_update(self, async_client: AsyncWhop) -> None: async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> None: company = await async_client.companies.update( id="biz_xxxxxxxxxxxxxx", + affiliate_application_required=True, + affiliate_instructions="affiliate_instructions", banner_image={"id": "id"}, description="description", + featured_affiliate_product_id="featured_affiliate_product_id", logo={"id": "id"}, route="route", send_customer_emails=True, diff --git a/tests/api_resources/test_invoices.py b/tests/api_resources/test_invoices.py index 7db7c12..97377e3 100644 --- a/tests/api_resources/test_invoices.py +++ b/tests/api_resources/test_invoices.py @@ -9,7 +9,11 @@ from whop_sdk import Whop, AsyncWhop from tests.utils import assert_matches_type -from whop_sdk.types import InvoiceVoidResponse +from whop_sdk.types import ( + InvoiceVoidResponse, + InvoiceMarkPaidResponse, + InvoiceMarkUncollectibleResponse, +) from whop_sdk._utils import parse_datetime from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage from whop_sdk.types.shared import Invoice, InvoiceListItem @@ -70,8 +74,28 @@ def test_method_create_with_all_params_overload_1(self, client: Whop) -> None: "product_tax_code_id": "ptc_xxxxxxxxxxxxxx", }, automatically_finalizes_at=parse_datetime("2023-12-01T05:00:00.401Z"), + billing_address={ + "city": "city", + "country": "country", + "line1": "line1", + "line2": "line2", + "name": "name", + "phone": "phone", + "postal_code": "postal_code", + "state": "state", + "tax_id_type": "ad_nrt", + "tax_id_value": "tax_id_value", + }, charge_buyer_fee=True, customer_name="customer_name", + line_items=[ + { + "label": "label", + "unit_price": 6.9, + "quantity": 6.9, + } + ], + mailing_address_id="ma_xxxxxxxxxxxxxxx", payment_method_id="pmt_xxxxxxxxxxxxxx", payment_token_id="payt_xxxxxxxxxxxxx", ) @@ -163,8 +187,28 @@ def test_method_create_with_all_params_overload_2(self, client: Whop) -> None: "product_tax_code_id": "ptc_xxxxxxxxxxxxxx", }, automatically_finalizes_at=parse_datetime("2023-12-01T05:00:00.401Z"), + billing_address={ + "city": "city", + "country": "country", + "line1": "line1", + "line2": "line2", + "name": "name", + "phone": "phone", + "postal_code": "postal_code", + "state": "state", + "tax_id_type": "ad_nrt", + "tax_id_value": "tax_id_value", + }, charge_buyer_fee=True, customer_name="customer_name", + line_items=[ + { + "label": "label", + "unit_price": 6.9, + "quantity": 6.9, + } + ], + mailing_address_id="ma_xxxxxxxxxxxxxxx", payment_method_id="pmt_xxxxxxxxxxxxxx", payment_token_id="payt_xxxxxxxxxxxxx", ) @@ -253,8 +297,28 @@ def test_method_create_with_all_params_overload_3(self, client: Whop) -> None: }, product_id="prod_xxxxxxxxxxxxx", automatically_finalizes_at=parse_datetime("2023-12-01T05:00:00.401Z"), + billing_address={ + "city": "city", + "country": "country", + "line1": "line1", + "line2": "line2", + "name": "name", + "phone": "phone", + "postal_code": "postal_code", + "state": "state", + "tax_id_type": "ad_nrt", + "tax_id_value": "tax_id_value", + }, charge_buyer_fee=True, customer_name="customer_name", + line_items=[ + { + "label": "label", + "unit_price": 6.9, + "quantity": 6.9, + } + ], + mailing_address_id="ma_xxxxxxxxxxxxxxx", payment_method_id="pmt_xxxxxxxxxxxxxx", payment_token_id="payt_xxxxxxxxxxxxx", ) @@ -343,8 +407,28 @@ def test_method_create_with_all_params_overload_4(self, client: Whop) -> None: }, product_id="prod_xxxxxxxxxxxxx", automatically_finalizes_at=parse_datetime("2023-12-01T05:00:00.401Z"), + billing_address={ + "city": "city", + "country": "country", + "line1": "line1", + "line2": "line2", + "name": "name", + "phone": "phone", + "postal_code": "postal_code", + "state": "state", + "tax_id_type": "ad_nrt", + "tax_id_value": "tax_id_value", + }, charge_buyer_fee=True, customer_name="customer_name", + line_items=[ + { + "label": "label", + "unit_price": 6.9, + "quantity": 6.9, + } + ], + mailing_address_id="ma_xxxxxxxxxxxxxxx", payment_method_id="pmt_xxxxxxxxxxxxxx", payment_token_id="payt_xxxxxxxxxxxxx", ) @@ -481,6 +565,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_mark_paid(self, client: Whop) -> None: + invoice = client.invoices.mark_paid( + "inv_xxxxxxxxxxxxxx", + ) + assert_matches_type(InvoiceMarkPaidResponse, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_mark_paid(self, client: Whop) -> None: + response = client.invoices.with_raw_response.mark_paid( + "inv_xxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + invoice = response.parse() + assert_matches_type(InvoiceMarkPaidResponse, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_mark_paid(self, client: Whop) -> None: + with client.invoices.with_streaming_response.mark_paid( + "inv_xxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + invoice = response.parse() + assert_matches_type(InvoiceMarkPaidResponse, invoice, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_mark_paid(self, client: Whop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.invoices.with_raw_response.mark_paid( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_mark_uncollectible(self, client: Whop) -> None: + invoice = client.invoices.mark_uncollectible( + "inv_xxxxxxxxxxxxxx", + ) + assert_matches_type(InvoiceMarkUncollectibleResponse, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_mark_uncollectible(self, client: Whop) -> None: + response = client.invoices.with_raw_response.mark_uncollectible( + "inv_xxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + invoice = response.parse() + assert_matches_type(InvoiceMarkUncollectibleResponse, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_mark_uncollectible(self, client: Whop) -> None: + with client.invoices.with_streaming_response.mark_uncollectible( + "inv_xxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + invoice = response.parse() + assert_matches_type(InvoiceMarkUncollectibleResponse, invoice, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_mark_uncollectible(self, client: Whop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.invoices.with_raw_response.mark_uncollectible( + "", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_void(self, client: Whop) -> None: @@ -579,8 +747,28 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn "product_tax_code_id": "ptc_xxxxxxxxxxxxxx", }, automatically_finalizes_at=parse_datetime("2023-12-01T05:00:00.401Z"), + billing_address={ + "city": "city", + "country": "country", + "line1": "line1", + "line2": "line2", + "name": "name", + "phone": "phone", + "postal_code": "postal_code", + "state": "state", + "tax_id_type": "ad_nrt", + "tax_id_value": "tax_id_value", + }, charge_buyer_fee=True, customer_name="customer_name", + line_items=[ + { + "label": "label", + "unit_price": 6.9, + "quantity": 6.9, + } + ], + mailing_address_id="ma_xxxxxxxxxxxxxxx", payment_method_id="pmt_xxxxxxxxxxxxxx", payment_token_id="payt_xxxxxxxxxxxxx", ) @@ -672,8 +860,28 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn "product_tax_code_id": "ptc_xxxxxxxxxxxxxx", }, automatically_finalizes_at=parse_datetime("2023-12-01T05:00:00.401Z"), + billing_address={ + "city": "city", + "country": "country", + "line1": "line1", + "line2": "line2", + "name": "name", + "phone": "phone", + "postal_code": "postal_code", + "state": "state", + "tax_id_type": "ad_nrt", + "tax_id_value": "tax_id_value", + }, charge_buyer_fee=True, customer_name="customer_name", + line_items=[ + { + "label": "label", + "unit_price": 6.9, + "quantity": 6.9, + } + ], + mailing_address_id="ma_xxxxxxxxxxxxxxx", payment_method_id="pmt_xxxxxxxxxxxxxx", payment_token_id="payt_xxxxxxxxxxxxx", ) @@ -762,8 +970,28 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn }, product_id="prod_xxxxxxxxxxxxx", automatically_finalizes_at=parse_datetime("2023-12-01T05:00:00.401Z"), + billing_address={ + "city": "city", + "country": "country", + "line1": "line1", + "line2": "line2", + "name": "name", + "phone": "phone", + "postal_code": "postal_code", + "state": "state", + "tax_id_type": "ad_nrt", + "tax_id_value": "tax_id_value", + }, charge_buyer_fee=True, customer_name="customer_name", + line_items=[ + { + "label": "label", + "unit_price": 6.9, + "quantity": 6.9, + } + ], + mailing_address_id="ma_xxxxxxxxxxxxxxx", payment_method_id="pmt_xxxxxxxxxxxxxx", payment_token_id="payt_xxxxxxxxxxxxx", ) @@ -852,8 +1080,28 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn }, product_id="prod_xxxxxxxxxxxxx", automatically_finalizes_at=parse_datetime("2023-12-01T05:00:00.401Z"), + billing_address={ + "city": "city", + "country": "country", + "line1": "line1", + "line2": "line2", + "name": "name", + "phone": "phone", + "postal_code": "postal_code", + "state": "state", + "tax_id_type": "ad_nrt", + "tax_id_value": "tax_id_value", + }, charge_buyer_fee=True, customer_name="customer_name", + line_items=[ + { + "label": "label", + "unit_price": 6.9, + "quantity": 6.9, + } + ], + mailing_address_id="ma_xxxxxxxxxxxxxxx", payment_method_id="pmt_xxxxxxxxxxxxxx", payment_token_id="payt_xxxxxxxxxxxxx", ) @@ -990,6 +1238,90 @@ async def test_streaming_response_list(self, async_client: AsyncWhop) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_mark_paid(self, async_client: AsyncWhop) -> None: + invoice = await async_client.invoices.mark_paid( + "inv_xxxxxxxxxxxxxx", + ) + assert_matches_type(InvoiceMarkPaidResponse, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_mark_paid(self, async_client: AsyncWhop) -> None: + response = await async_client.invoices.with_raw_response.mark_paid( + "inv_xxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + invoice = await response.parse() + assert_matches_type(InvoiceMarkPaidResponse, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_mark_paid(self, async_client: AsyncWhop) -> None: + async with async_client.invoices.with_streaming_response.mark_paid( + "inv_xxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + invoice = await response.parse() + assert_matches_type(InvoiceMarkPaidResponse, invoice, 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_mark_paid(self, async_client: AsyncWhop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.invoices.with_raw_response.mark_paid( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_mark_uncollectible(self, async_client: AsyncWhop) -> None: + invoice = await async_client.invoices.mark_uncollectible( + "inv_xxxxxxxxxxxxxx", + ) + assert_matches_type(InvoiceMarkUncollectibleResponse, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_mark_uncollectible(self, async_client: AsyncWhop) -> None: + response = await async_client.invoices.with_raw_response.mark_uncollectible( + "inv_xxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + invoice = await response.parse() + assert_matches_type(InvoiceMarkUncollectibleResponse, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_mark_uncollectible(self, async_client: AsyncWhop) -> None: + async with async_client.invoices.with_streaming_response.mark_uncollectible( + "inv_xxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + invoice = await response.parse() + assert_matches_type(InvoiceMarkUncollectibleResponse, invoice, 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_mark_uncollectible(self, async_client: AsyncWhop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.invoices.with_raw_response.mark_uncollectible( + "", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_void(self, async_client: AsyncWhop) -> None: diff --git a/tests/api_resources/test_payments.py b/tests/api_resources/test_payments.py index e16cc67..628f7f7 100644 --- a/tests/api_resources/test_payments.py +++ b/tests/api_resources/test_payments.py @@ -43,6 +43,7 @@ def test_method_create_with_all_params_overload_1(self, client: Whop) -> None: payment_method_id="pmt_xxxxxxxxxxxxxx", plan={ "currency": "usd", + "application_fee_amount": 6.9, "billing_period": 42, "description": "description", "expiration_days": 42, @@ -230,6 +231,8 @@ def test_method_list_with_all_params(self, client: Whop) -> None: query="query", statuses=["draft"], substatuses=["succeeded"], + updated_after=parse_datetime("2023-12-01T05:00:00.401Z"), + updated_before=parse_datetime("2023-12-01T05:00:00.401Z"), ) assert_matches_type(SyncCursorPage[PaymentListResponse], payment, path=["response"]) @@ -470,6 +473,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn payment_method_id="pmt_xxxxxxxxxxxxxx", plan={ "currency": "usd", + "application_fee_amount": 6.9, "billing_period": 42, "description": "description", "expiration_days": 42, @@ -657,6 +661,8 @@ async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> Non query="query", statuses=["draft"], substatuses=["succeeded"], + updated_after=parse_datetime("2023-12-01T05:00:00.401Z"), + updated_before=parse_datetime("2023-12-01T05:00:00.401Z"), ) assert_matches_type(AsyncCursorPage[PaymentListResponse], payment, path=["response"]) diff --git a/tests/api_resources/test_plans.py b/tests/api_resources/test_plans.py index 296e431..33d2cfc 100644 --- a/tests/api_resources/test_plans.py +++ b/tests/api_resources/test_plans.py @@ -39,6 +39,11 @@ def test_method_create_with_all_params(self, client: Whop) -> None: company_id="biz_xxxxxxxxxxxxxx", product_id="prod_xxxxxxxxxxxxx", billing_period=42, + checkout_styling={ + "border_style": "rounded", + "button_color": "button_color", + "font_family": "system", + }, currency="usd", custom_fields=[ { @@ -158,6 +163,11 @@ def test_method_update_with_all_params(self, client: Whop) -> None: plan = client.plans.update( id="plan_xxxxxxxxxxxxx", billing_period=42, + checkout_styling={ + "border_style": "rounded", + "button_color": "button_color", + "font_family": "system", + }, currency="usd", custom_fields=[ { @@ -345,6 +355,11 @@ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> N company_id="biz_xxxxxxxxxxxxxx", product_id="prod_xxxxxxxxxxxxx", billing_period=42, + checkout_styling={ + "border_style": "rounded", + "button_color": "button_color", + "font_family": "system", + }, currency="usd", custom_fields=[ { @@ -464,6 +479,11 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N plan = await async_client.plans.update( id="plan_xxxxxxxxxxxxx", billing_period=42, + checkout_styling={ + "border_style": "rounded", + "button_color": "button_color", + "font_family": "system", + }, currency="usd", custom_fields=[ { diff --git a/tests/test_utils/test_path.py b/tests/test_utils/test_path.py new file mode 100644 index 0000000..bb4a49a --- /dev/null +++ b/tests/test_utils/test_path.py @@ -0,0 +1,89 @@ +from __future__ import annotations + +from typing import Any + +import pytest + +from whop_sdk._utils._path import path_template + + +@pytest.mark.parametrize( + "template, kwargs, expected", + [ + ("/v1/{id}", dict(id="abc"), "/v1/abc"), + ("/v1/{a}/{b}", dict(a="x", b="y"), "/v1/x/y"), + ("/v1/{a}{b}/path/{c}?val={d}#{e}", dict(a="x", b="y", c="z", d="u", e="v"), "/v1/xy/path/z?val=u#v"), + ("/{w}/{w}", dict(w="echo"), "/echo/echo"), + ("/v1/static", {}, "/v1/static"), + ("", {}, ""), + ("/v1/?q={n}&count=10", dict(n=42), "/v1/?q=42&count=10"), + ("/v1/{v}", dict(v=None), "/v1/null"), + ("/v1/{v}", dict(v=True), "/v1/true"), + ("/v1/{v}", dict(v=False), "/v1/false"), + ("/v1/{v}", dict(v=".hidden"), "/v1/.hidden"), # dot prefix ok + ("/v1/{v}", dict(v="file.txt"), "/v1/file.txt"), # dot in middle ok + ("/v1/{v}", dict(v="..."), "/v1/..."), # triple dot ok + ("/v1/{a}{b}", dict(a=".", b="txt"), "/v1/.txt"), # dot var combining with adjacent to be ok + ("/items?q={v}#{f}", dict(v=".", f=".."), "/items?q=.#.."), # dots in query/fragment are fine + ( + "/v1/{a}?query={b}", + dict(a="../../other/endpoint", b="a&bad=true"), + "/v1/..%2F..%2Fother%2Fendpoint?query=a%26bad%3Dtrue", + ), + ("/v1/{val}", dict(val="a/b/c"), "/v1/a%2Fb%2Fc"), + ("/v1/{val}", dict(val="a/b/c?query=value"), "/v1/a%2Fb%2Fc%3Fquery=value"), + ("/v1/{val}", dict(val="a/b/c?query=value&bad=true"), "/v1/a%2Fb%2Fc%3Fquery=value&bad=true"), + ("/v1/{val}", dict(val="%20"), "/v1/%2520"), # escapes escape sequences in input + # Query: slash and ? are safe, # is not + ("/items?q={v}", dict(v="a/b"), "/items?q=a/b"), + ("/items?q={v}", dict(v="a?b"), "/items?q=a?b"), + ("/items?q={v}", dict(v="a#b"), "/items?q=a%23b"), + ("/items?q={v}", dict(v="a b"), "/items?q=a%20b"), + # Fragment: slash and ? are safe + ("/docs#{v}", dict(v="a/b"), "/docs#a/b"), + ("/docs#{v}", dict(v="a?b"), "/docs#a?b"), + # Path: slash, ? and # are all encoded + ("/v1/{v}", dict(v="a/b"), "/v1/a%2Fb"), + ("/v1/{v}", dict(v="a?b"), "/v1/a%3Fb"), + ("/v1/{v}", dict(v="a#b"), "/v1/a%23b"), + # same var encoded differently by component + ( + "/v1/{v}?q={v}#{v}", + dict(v="a/b?c#d"), + "/v1/a%2Fb%3Fc%23d?q=a/b?c%23d#a/b?c%23d", + ), + ("/v1/{val}", dict(val="x?admin=true"), "/v1/x%3Fadmin=true"), # query injection + ("/v1/{val}", dict(val="x#admin"), "/v1/x%23admin"), # fragment injection + ], +) +def test_interpolation(template: str, kwargs: dict[str, Any], expected: str) -> None: + assert path_template(template, **kwargs) == expected + + +def test_missing_kwarg_raises_key_error() -> None: + with pytest.raises(KeyError, match="org_id"): + path_template("/v1/{org_id}") + + +@pytest.mark.parametrize( + "template, kwargs", + [ + ("{a}/path", dict(a=".")), + ("{a}/path", dict(a="..")), + ("/v1/{a}", dict(a=".")), + ("/v1/{a}", dict(a="..")), + ("/v1/{a}/path", dict(a=".")), + ("/v1/{a}/path", dict(a="..")), + ("/v1/{a}{b}", dict(a=".", b=".")), # adjacent vars → ".." + ("/v1/{a}.", dict(a=".")), # var + static → ".." + ("/v1/{a}{b}", dict(a="", b=".")), # empty + dot → "." + ("/v1/%2e/{x}", dict(x="ok")), # encoded dot in static text + ("/v1/%2e./{x}", dict(x="ok")), # mixed encoded ".." in static + ("/v1/.%2E/{x}", dict(x="ok")), # mixed encoded ".." in static + ("/v1/{v}?q=1", dict(v="..")), + ("/v1/{v}#frag", dict(v="..")), + ], +) +def test_dot_segment_rejected(template: str, kwargs: dict[str, Any]) -> None: + with pytest.raises(ValueError, match="dot-segment"): + path_template(template, **kwargs)