diff --git a/.release-please-manifest.json b/.release-please-manifest.json index cacb3a0..423c69f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.36" + ".": "0.0.37" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 32314d6..fc1b600 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -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 +configured_endpoints: 195 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-58749e1928f402cc3e236d38b53bce3b10530bfaccbe426181bba9b1bfc42498.yml +openapi_spec_hash: ecea6e6c4b93665aee5554839a26ded8 +config_hash: 2ceaf6cd488db626c181a1ca9460ace6 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cb411b..37f7a9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## 0.0.37 (2026-04-10) + +Full Changelog: [v0.0.36...v0.0.37](https://github.com/whopio/whopsdk-python/compare/v0.0.36...v0.0.37) + +### Features + +* **api:** api update ([d2693a0](https://github.com/whopio/whopsdk-python/commit/d2693a0106620b442ef9e981cd8f8cc44ef26e8f)) +* **api:** api update ([1e398a6](https://github.com/whopio/whopsdk-python/commit/1e398a68ff927c66eefaef4eae88fb2aecef9581)) +* **api:** api update ([d17a56f](https://github.com/whopio/whopsdk-python/commit/d17a56ff7a5e89ce7863e3d44bd06912fc3ce94c)) +* **api:** api update ([b85a378](https://github.com/whopio/whopsdk-python/commit/b85a3787bb1871cb46cbdde7bb809f590cb143ef)) +* **api:** manual updates ([c401009](https://github.com/whopio/whopsdk-python/commit/c40100933895bfe8f2f20d480e8348b7092b4c89)) + + +### Bug Fixes + +* **client:** preserve hardcoded query params when merging with user params ([2a7a622](https://github.com/whopio/whopsdk-python/commit/2a7a622f89f262b1b2b6df0fb6354947db0e20f9)) + ## 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) diff --git a/api.md b/api.md index 1d4b939..c925e6e 100644 --- a/api.md +++ b/api.md @@ -85,6 +85,7 @@ Types: ```python from whop_sdk.types import ( TaxIdentifierType, + InvoiceDeleteResponse, InvoiceMarkPaidResponse, InvoiceMarkUncollectibleResponse, InvoiceVoidResponse, @@ -95,7 +96,9 @@ Methods: - client.invoices.create(\*\*params) -> Invoice - client.invoices.retrieve(id) -> Invoice +- client.invoices.update(id, \*\*params) -> Invoice - client.invoices.list(\*\*params) -> SyncCursorPage[InvoiceListItem] +- client.invoices.delete(id) -> InvoiceDeleteResponse - client.invoices.mark_paid(id) -> InvoiceMarkPaidResponse - client.invoices.mark_uncollectible(id) -> InvoiceMarkUncollectibleResponse - client.invoices.void(id) -> InvoiceVoidResponse @@ -200,7 +203,7 @@ Methods: Types: ```python -from whop_sdk.types import PlanListResponse, PlanDeleteResponse +from whop_sdk.types import CheckoutFont, CheckoutShape, PlanListResponse, PlanDeleteResponse ``` Methods: diff --git a/pyproject.toml b/pyproject.toml index 9056f9e..4719b5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "whop-sdk" -version = "0.0.36" +version = "0.0.37" description = "The official Python library for the Whop API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/whop_sdk/_base_client.py b/src/whop_sdk/_base_client.py index 2eac6fe..5089b11 100644 --- a/src/whop_sdk/_base_client.py +++ b/src/whop_sdk/_base_client.py @@ -540,6 +540,10 @@ def _build_request( files = cast(HttpxRequestFiles, ForceMultipartDict()) prepared_url = self._prepare_url(options.url) + # preserve hard-coded query params from the url + if params and prepared_url.query: + params = {**dict(prepared_url.params.items()), **params} + prepared_url = prepared_url.copy_with(raw_path=prepared_url.raw_path.split(b"?", 1)[0]) if "_" in prepared_url.host: # work around https://github.com/encode/httpx/discussions/2880 kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")} diff --git a/src/whop_sdk/_version.py b/src/whop_sdk/_version.py index 75c4782..a1018dc 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.36" # x-release-please-version +__version__ = "0.0.37" # x-release-please-version diff --git a/src/whop_sdk/resources/invoices.py b/src/whop_sdk/resources/invoices.py index b3ef3f2..11363bc 100644 --- a/src/whop_sdk/resources/invoices.py +++ b/src/whop_sdk/resources/invoices.py @@ -8,7 +8,7 @@ import httpx -from ..types import invoice_list_params, invoice_create_params +from ..types import invoice_list_params, invoice_create_params, invoice_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from .._utils import path_template, required_args, maybe_transform, async_maybe_transform from .._compat import cached_property @@ -25,6 +25,7 @@ from ..types.shared.direction import Direction from ..types.invoice_void_response import InvoiceVoidResponse from ..types.shared.invoice_status import InvoiceStatus +from ..types.invoice_delete_response import InvoiceDeleteResponse from ..types.shared.collection_method import CollectionMethod from ..types.shared.invoice_list_item import InvoiceListItem from ..types.invoice_mark_paid_response import InvoiceMarkPaidResponse @@ -59,20 +60,20 @@ def create( *, collection_method: CollectionMethod, company_id: str, - due_date: Union[str, datetime], - member_id: str, - plan: invoice_create_params.CreateInvoiceInputWithProductAndMemberIDPlan, - product: invoice_create_params.CreateInvoiceInputWithProductAndMemberIDProduct, + plan: invoice_create_params.CreateInvoiceInputWithProductPlan, + product: invoice_create_params.CreateInvoiceInputWithProductProduct, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, - billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductAndMemberIDBillingAddress] - | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductBillingAddress] | 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, + due_date: Union[str, datetime, None] | Omit = omit, + email_address: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductLineItem]] | Omit = omit, mailing_address_id: Optional[str] | Omit = omit, + member_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, + save_as_draft: Optional[bool] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -96,11 +97,6 @@ def create( company_id: The unique identifier of the company to create this invoice for. - due_date: The date by which the invoice must be paid. - - member_id: The unique identifier of an existing member to create this invoice for. If not - provided, you must supply an email_address and customer_name. - plan: The plan attributes defining the price, currency, and billing interval for this invoice. @@ -119,106 +115,30 @@ def create( 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. - - payment_token_id: The payment token ID to use for this invoice. If using charge_automatically, you - must provide a payment_token. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def create( - self, - *, - collection_method: CollectionMethod, - company_id: str, - due_date: Union[str, datetime], - email_address: str, - 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. - # 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, - ) -> Invoice: - """Create an invoice for a customer. - - The invoice can be charged automatically using - a stored payment method, or sent to the customer for manual payment. - - Required permissions: - - - `invoice:create` - - `plan:basic:read` - - Args: - collection_method: How the invoice should be collected. Use charge_automatically to charge a stored - payment method, or send_invoice to email the customer. - - company_id: The unique identifier of the company to create this invoice for. - - due_date: The date by which the invoice must be paid. + due_date: The date by which the invoice must be paid. Required unless save_as_draft is + true. email_address: The email address of the customer. Required when creating an invoice for a customer who is not yet a member of the company. - plan: The plan attributes defining the price, currency, and billing interval for this - invoice. - - product: The properties of the product to create for this invoice. Provide this to create - a new product inline. - - automatically_finalizes_at: The date and time when the invoice will be automatically finalized and charged. - 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. + member_id: The unique identifier of an existing member to create this invoice for. If not + provided, you must supply an email_address and customer_name. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. payment_token_id: The payment token ID to use for this invoice. If using charge_automatically, you must provide a payment_token. + save_as_draft: When true, creates the invoice as a draft without sending or charging. Relaxes + customer and due date requirements. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -235,20 +155,20 @@ def create( *, collection_method: CollectionMethod, company_id: str, - due_date: Union[str, datetime], - member_id: str, - plan: invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDPlan, + plan: invoice_create_params.CreateInvoiceInputWithProductIDPlan, product_id: str, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, - billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDBillingAddress] - | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductIDBillingAddress] | 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, + due_date: Union[str, datetime, None] | Omit = omit, + email_address: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductIDLineItem]] | Omit = omit, mailing_address_id: Optional[str] | Omit = omit, + member_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, + save_as_draft: Optional[bool] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -272,11 +192,6 @@ def create( company_id: The unique identifier of the company to create this invoice for. - due_date: The date by which the invoice must be paid. - - member_id: The unique identifier of an existing member to create this invoice for. If not - provided, you must supply an email_address and customer_name. - plan: The plan attributes defining the price, currency, and billing interval for this invoice. @@ -294,105 +209,30 @@ def create( 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. - - payment_token_id: The payment token ID to use for this invoice. If using charge_automatically, you - must provide a payment_token. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def create( - self, - *, - collection_method: CollectionMethod, - company_id: str, - due_date: Union[str, datetime], - email_address: str, - 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. - # 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, - ) -> Invoice: - """Create an invoice for a customer. - - The invoice can be charged automatically using - a stored payment method, or sent to the customer for manual payment. - - Required permissions: - - - `invoice:create` - - `plan:basic:read` - - Args: - collection_method: How the invoice should be collected. Use charge_automatically to charge a stored - payment method, or send_invoice to email the customer. - - company_id: The unique identifier of the company to create this invoice for. - - due_date: The date by which the invoice must be paid. + due_date: The date by which the invoice must be paid. Required unless save_as_draft is + true. email_address: The email address of the customer. Required when creating an invoice for a customer who is not yet a member of the company. - plan: The plan attributes defining the price, currency, and billing interval for this - invoice. - - product_id: The unique identifier of an existing product to create this invoice for. - - automatically_finalizes_at: The date and time when the invoice will be automatically finalized and charged. - 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. + member_id: The unique identifier of an existing member to create this invoice for. If not + provided, you must supply an email_address and customer_name. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. payment_token_id: The payment token ID to use for this invoice. If using charge_automatically, you must provide a payment_token. + save_as_draft: When true, creates the invoice as a draft without sending or charging. Relaxes + customer and due date requirements. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -404,39 +244,31 @@ def create( ... @required_args( - ["collection_method", "company_id", "due_date", "member_id", "plan", "product"], - ["collection_method", "company_id", "due_date", "email_address", "plan", "product"], - ["collection_method", "company_id", "due_date", "member_id", "plan", "product_id"], - ["collection_method", "company_id", "due_date", "email_address", "plan", "product_id"], + ["collection_method", "company_id", "plan", "product"], + ["collection_method", "company_id", "plan", "product_id"], ) def create( self, *, collection_method: CollectionMethod, company_id: str, - due_date: Union[str, datetime], - member_id: str | Omit = omit, - plan: invoice_create_params.CreateInvoiceInputWithProductAndMemberIDPlan - | invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressPlan - | invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDPlan - | invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressPlan, - product: invoice_create_params.CreateInvoiceInputWithProductAndMemberIDProduct - | invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressProduct - | Omit = omit, + plan: invoice_create_params.CreateInvoiceInputWithProductPlan + | invoice_create_params.CreateInvoiceInputWithProductIDPlan, + product: invoice_create_params.CreateInvoiceInputWithProductProduct | 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] + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductBillingAddress] + | Optional[invoice_create_params.CreateInvoiceInputWithProductIDBillingAddress] | 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, + due_date: Union[str, datetime, None] | Omit = omit, + email_address: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductLineItem]] | Omit = omit, mailing_address_id: Optional[str] | Omit = omit, + member_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, - email_address: str | Omit = omit, + save_as_draft: Optional[bool] | Omit = omit, product_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -451,19 +283,20 @@ def create( { "collection_method": collection_method, "company_id": company_id, - "due_date": due_date, - "member_id": member_id, "plan": plan, "product": product, "automatically_finalizes_at": automatically_finalizes_at, "billing_address": billing_address, "charge_buyer_fee": charge_buyer_fee, "customer_name": customer_name, + "due_date": due_date, + "email_address": email_address, "line_items": line_items, "mailing_address_id": mailing_address_id, + "member_id": member_id, "payment_method_id": payment_method_id, "payment_token_id": payment_token_id, - "email_address": email_address, + "save_as_draft": save_as_draft, "product_id": product_id, }, invoice_create_params.InvoiceCreateParams, @@ -512,6 +345,96 @@ def retrieve( cast_to=Invoice, ) + def update( + self, + id: str, + *, + automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_update_params.BillingAddress] | Omit = omit, + charge_buyer_fee: Optional[bool] | Omit = omit, + collection_method: Optional[CollectionMethod] | Omit = omit, + customer_name: Optional[str] | Omit = omit, + due_date: Union[str, datetime, None] | Omit = omit, + email_address: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_update_params.LineItem]] | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, + member_id: Optional[str] | Omit = omit, + payment_method_id: Optional[str] | Omit = omit, + plan: Optional[invoice_update_params.Plan] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Invoice: + """ + Update a draft invoice's details. + + Required permissions: + + - `invoice:update` + + Args: + automatically_finalizes_at: The date and time when the invoice will be automatically finalized and charged. + + billing_address: Inline billing address to create or update a mailing address for this invoice. + + charge_buyer_fee: Whether to charge the customer a buyer fee on this invoice. + + collection_method: The method of collection for an invoice. + + customer_name: The name of the customer. + + due_date: The date by which the invoice must be paid. + + email_address: The email address of the customer. + + line_items: Line items that break down the invoice total. + + mailing_address_id: The unique identifier of an existing mailing address to attach. + + member_id: The unique identifier of a member to assign as the customer. + + payment_method_id: The unique identifier of the payment method to charge. + + plan: Updated plan attributes. + + 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._patch( + path_template("/invoices/{id}", id=id), + body=maybe_transform( + { + "automatically_finalizes_at": automatically_finalizes_at, + "billing_address": billing_address, + "charge_buyer_fee": charge_buyer_fee, + "collection_method": collection_method, + "customer_name": customer_name, + "due_date": due_date, + "email_address": email_address, + "line_items": line_items, + "mailing_address_id": mailing_address_id, + "member_id": member_id, + "payment_method_id": payment_method_id, + "plan": plan, + }, + invoice_update_params.InvoiceUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Invoice, + ) + def list( self, *, @@ -606,7 +529,7 @@ def list( model=InvoiceListItem, ) - def mark_paid( + def delete( self, id: str, *, @@ -616,9 +539,9 @@ def mark_paid( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> InvoiceMarkPaidResponse: + ) -> InvoiceDeleteResponse: """ - Mark an open invoice as paid when payment was collected outside of Whop. + Delete a draft invoice. Required permissions: @@ -635,15 +558,15 @@ def mark_paid( """ 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), + return self._delete( + path_template("/invoices/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=InvoiceMarkPaidResponse, + cast_to=InvoiceDeleteResponse, ) - def mark_uncollectible( + def mark_paid( self, id: str, *, @@ -653,9 +576,9 @@ def mark_uncollectible( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> InvoiceMarkUncollectibleResponse: + ) -> InvoiceMarkPaidResponse: """ - Mark an open invoice as uncollectible when payment is not expected. + Mark an open invoice as paid when payment was collected outside of Whop. Required permissions: @@ -673,14 +596,14 @@ def mark_uncollectible( 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), + 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=InvoiceMarkUncollectibleResponse, + cast_to=InvoiceMarkPaidResponse, ) - def void( + def mark_uncollectible( self, id: str, *, @@ -690,134 +613,15 @@ def void( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> InvoiceVoidResponse: - """Void an open invoice so it can no longer be paid. - - Voiding is permanent and - cannot be undone. - - 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}/void", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=InvoiceVoidResponse, - ) - - -class AsyncInvoicesResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncInvoicesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/whopio/whopsdk-python#accessing-raw-response-data-eg-headers - """ - return AsyncInvoicesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncInvoicesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/whopio/whopsdk-python#with_streaming_response + ) -> InvoiceMarkUncollectibleResponse: """ - return AsyncInvoicesResourceWithStreamingResponse(self) - - @overload - async def create( - self, - *, - collection_method: CollectionMethod, - company_id: str, - due_date: Union[str, datetime], - member_id: str, - 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. - # 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, - ) -> Invoice: - """Create an invoice for a customer. - - The invoice can be charged automatically using - a stored payment method, or sent to the customer for manual payment. + Mark an open invoice as uncollectible when payment is not expected. Required permissions: - - `invoice:create` - - `plan:basic:read` + - `invoice:update` Args: - collection_method: How the invoice should be collected. Use charge_automatically to charge a stored - payment method, or send_invoice to email the customer. - - company_id: The unique identifier of the company to create this invoice for. - - due_date: The date by which the invoice must be paid. - - member_id: The unique identifier of an existing member to create this invoice for. If not - provided, you must supply an email_address and customer_name. - - plan: The plan attributes defining the price, currency, and billing interval for this - invoice. - - product: The properties of the product to create for this invoice. Provide this to create - a new product inline. - - automatically_finalizes_at: The date and time when the invoice will be automatically finalized and charged. - 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. - - payment_token_id: The payment token ID to use for this invoice. If using charge_automatically, you - must provide a payment_token. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -826,95 +630,75 @@ async def create( 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, + ) - @overload - async def create( + def void( self, + id: str, *, - collection_method: CollectionMethod, - company_id: str, - due_date: Union[str, datetime], - email_address: str, - 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. # 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, - ) -> Invoice: - """Create an invoice for a customer. + ) -> InvoiceVoidResponse: + """Void an open invoice so it can no longer be paid. - The invoice can be charged automatically using - a stored payment method, or sent to the customer for manual payment. + Voiding is permanent and + cannot be undone. Required permissions: - - `invoice:create` - - `plan:basic:read` + - `invoice:update` Args: - collection_method: How the invoice should be collected. Use charge_automatically to charge a stored - payment method, or send_invoice to email the customer. - - company_id: The unique identifier of the company to create this invoice for. - - due_date: The date by which the invoice must be paid. - - email_address: The email address of the customer. Required when creating an invoice for a - customer who is not yet a member of the company. - - plan: The plan attributes defining the price, currency, and billing interval for this - invoice. - - product: The properties of the product to create for this invoice. Provide this to create - a new product inline. - - automatically_finalizes_at: The date and time when the invoice will be automatically finalized and charged. - 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. + extra_headers: Send extra headers - 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. + extra_query: Add additional query parameters to the request - mailing_address_id: The unique identifier of an existing mailing address to attach to this invoice. - Cannot be used together with billing_address. + extra_body: Add additional JSON properties to the request - payment_method_id: The unique identifier of the payment method to charge. Required when - collection_method is charge_automatically. + 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}/void", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InvoiceVoidResponse, + ) - payment_token_id: The payment token ID to use for this invoice. If using charge_automatically, you - must provide a payment_token. - extra_headers: Send extra headers +class AsyncInvoicesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncInvoicesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. - extra_query: Add additional query parameters to the request + For more information, see https://www.github.com/whopio/whopsdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncInvoicesResourceWithRawResponse(self) - extra_body: Add additional JSON properties to the request + @cached_property + def with_streaming_response(self) -> AsyncInvoicesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. - timeout: Override the client-level default timeout for this request, in seconds + For more information, see https://www.github.com/whopio/whopsdk-python#with_streaming_response """ - ... + return AsyncInvoicesResourceWithStreamingResponse(self) @overload async def create( @@ -922,20 +706,20 @@ async def create( *, collection_method: CollectionMethod, company_id: str, - due_date: Union[str, datetime], - member_id: str, - plan: invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDPlan, - product_id: str, + plan: invoice_create_params.CreateInvoiceInputWithProductPlan, + product: invoice_create_params.CreateInvoiceInputWithProductProduct, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, - billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDBillingAddress] - | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductBillingAddress] | 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, + due_date: Union[str, datetime, None] | Omit = omit, + email_address: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductLineItem]] | Omit = omit, mailing_address_id: Optional[str] | Omit = omit, + member_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, + save_as_draft: Optional[bool] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -959,15 +743,11 @@ async def create( company_id: The unique identifier of the company to create this invoice for. - due_date: The date by which the invoice must be paid. - - member_id: The unique identifier of an existing member to create this invoice for. If not - provided, you must supply an email_address and customer_name. - plan: The plan attributes defining the price, currency, and billing interval for this invoice. - product_id: The unique identifier of an existing product to create this invoice for. + product: The properties of the product to create for this invoice. Provide this to create + a new product inline. automatically_finalizes_at: The date and time when the invoice will be automatically finalized and charged. Only valid when collection_method is charge_automatically. If not provided, the @@ -981,18 +761,30 @@ async def create( customer_name: The name of the customer. Required when creating an invoice for a customer who is not yet a member of the company. + due_date: The date by which the invoice must be paid. Required unless save_as_draft is + true. + + email_address: The email address 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. + member_id: The unique identifier of an existing member to create this invoice for. If not + provided, you must supply an email_address and customer_name. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. payment_token_id: The payment token ID to use for this invoice. If using charge_automatically, you must provide a payment_token. + save_as_draft: When true, creates the invoice as a draft without sending or charging. Relaxes + customer and due date requirements. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1009,20 +801,20 @@ async def create( *, collection_method: CollectionMethod, company_id: str, - due_date: Union[str, datetime], - email_address: str, - plan: invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressPlan, + plan: invoice_create_params.CreateInvoiceInputWithProductIDPlan, product_id: str, automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, - billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressBillingAddress] - | Omit = omit, + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductIDBillingAddress] | 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, + due_date: Union[str, datetime, None] | Omit = omit, + email_address: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductIDLineItem]] | Omit = omit, mailing_address_id: Optional[str] | Omit = omit, + member_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, + save_as_draft: Optional[bool] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1046,11 +838,6 @@ async def create( company_id: The unique identifier of the company to create this invoice for. - due_date: The date by which the invoice must be paid. - - email_address: The email address of the customer. Required when creating an invoice for a - customer who is not yet a member of the company. - plan: The plan attributes defining the price, currency, and billing interval for this invoice. @@ -1068,18 +855,30 @@ async def create( customer_name: The name of the customer. Required when creating an invoice for a customer who is not yet a member of the company. + due_date: The date by which the invoice must be paid. Required unless save_as_draft is + true. + + email_address: The email address 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. + member_id: The unique identifier of an existing member to create this invoice for. If not + provided, you must supply an email_address and customer_name. + payment_method_id: The unique identifier of the payment method to charge. Required when collection_method is charge_automatically. payment_token_id: The payment token ID to use for this invoice. If using charge_automatically, you must provide a payment_token. + save_as_draft: When true, creates the invoice as a draft without sending or charging. Relaxes + customer and due date requirements. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1091,39 +890,31 @@ async def create( ... @required_args( - ["collection_method", "company_id", "due_date", "member_id", "plan", "product"], - ["collection_method", "company_id", "due_date", "email_address", "plan", "product"], - ["collection_method", "company_id", "due_date", "member_id", "plan", "product_id"], - ["collection_method", "company_id", "due_date", "email_address", "plan", "product_id"], + ["collection_method", "company_id", "plan", "product"], + ["collection_method", "company_id", "plan", "product_id"], ) async def create( self, *, collection_method: CollectionMethod, company_id: str, - due_date: Union[str, datetime], - member_id: str | Omit = omit, - plan: invoice_create_params.CreateInvoiceInputWithProductAndMemberIDPlan - | invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressPlan - | invoice_create_params.CreateInvoiceInputWithProductIDAndMemberIDPlan - | invoice_create_params.CreateInvoiceInputWithProductIDAndEmailAddressPlan, - product: invoice_create_params.CreateInvoiceInputWithProductAndMemberIDProduct - | invoice_create_params.CreateInvoiceInputWithProductAndEmailAddressProduct - | Omit = omit, + plan: invoice_create_params.CreateInvoiceInputWithProductPlan + | invoice_create_params.CreateInvoiceInputWithProductIDPlan, + product: invoice_create_params.CreateInvoiceInputWithProductProduct | 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] + billing_address: Optional[invoice_create_params.CreateInvoiceInputWithProductBillingAddress] + | Optional[invoice_create_params.CreateInvoiceInputWithProductIDBillingAddress] | 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, + due_date: Union[str, datetime, None] | Omit = omit, + email_address: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_create_params.CreateInvoiceInputWithProductLineItem]] | Omit = omit, mailing_address_id: Optional[str] | Omit = omit, + member_id: Optional[str] | Omit = omit, payment_method_id: Optional[str] | Omit = omit, payment_token_id: Optional[str] | Omit = omit, - email_address: str | Omit = omit, + save_as_draft: Optional[bool] | Omit = omit, product_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -1138,19 +929,20 @@ async def create( { "collection_method": collection_method, "company_id": company_id, - "due_date": due_date, - "member_id": member_id, "plan": plan, "product": product, "automatically_finalizes_at": automatically_finalizes_at, "billing_address": billing_address, "charge_buyer_fee": charge_buyer_fee, "customer_name": customer_name, + "due_date": due_date, + "email_address": email_address, "line_items": line_items, "mailing_address_id": mailing_address_id, + "member_id": member_id, "payment_method_id": payment_method_id, "payment_token_id": payment_token_id, - "email_address": email_address, + "save_as_draft": save_as_draft, "product_id": product_id, }, invoice_create_params.InvoiceCreateParams, @@ -1199,6 +991,96 @@ async def retrieve( cast_to=Invoice, ) + async def update( + self, + id: str, + *, + automatically_finalizes_at: Union[str, datetime, None] | Omit = omit, + billing_address: Optional[invoice_update_params.BillingAddress] | Omit = omit, + charge_buyer_fee: Optional[bool] | Omit = omit, + collection_method: Optional[CollectionMethod] | Omit = omit, + customer_name: Optional[str] | Omit = omit, + due_date: Union[str, datetime, None] | Omit = omit, + email_address: Optional[str] | Omit = omit, + line_items: Optional[Iterable[invoice_update_params.LineItem]] | Omit = omit, + mailing_address_id: Optional[str] | Omit = omit, + member_id: Optional[str] | Omit = omit, + payment_method_id: Optional[str] | Omit = omit, + plan: Optional[invoice_update_params.Plan] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Invoice: + """ + Update a draft invoice's details. + + Required permissions: + + - `invoice:update` + + Args: + automatically_finalizes_at: The date and time when the invoice will be automatically finalized and charged. + + billing_address: Inline billing address to create or update a mailing address for this invoice. + + charge_buyer_fee: Whether to charge the customer a buyer fee on this invoice. + + collection_method: The method of collection for an invoice. + + customer_name: The name of the customer. + + due_date: The date by which the invoice must be paid. + + email_address: The email address of the customer. + + line_items: Line items that break down the invoice total. + + mailing_address_id: The unique identifier of an existing mailing address to attach. + + member_id: The unique identifier of a member to assign as the customer. + + payment_method_id: The unique identifier of the payment method to charge. + + plan: Updated plan attributes. + + 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._patch( + path_template("/invoices/{id}", id=id), + body=await async_maybe_transform( + { + "automatically_finalizes_at": automatically_finalizes_at, + "billing_address": billing_address, + "charge_buyer_fee": charge_buyer_fee, + "collection_method": collection_method, + "customer_name": customer_name, + "due_date": due_date, + "email_address": email_address, + "line_items": line_items, + "mailing_address_id": mailing_address_id, + "member_id": member_id, + "payment_method_id": payment_method_id, + "plan": plan, + }, + invoice_update_params.InvoiceUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Invoice, + ) + def list( self, *, @@ -1293,6 +1175,43 @@ def list( model=InvoiceListItem, ) + async def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> InvoiceDeleteResponse: + """ + Delete a draft invoice. + + 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._delete( + path_template("/invoices/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InvoiceDeleteResponse, + ) + async def mark_paid( self, id: str, @@ -1417,9 +1336,15 @@ def __init__(self, invoices: InvoicesResource) -> None: self.retrieve = to_raw_response_wrapper( invoices.retrieve, ) + self.update = to_raw_response_wrapper( + invoices.update, + ) self.list = to_raw_response_wrapper( invoices.list, ) + self.delete = to_raw_response_wrapper( + invoices.delete, + ) self.mark_paid = to_raw_response_wrapper( invoices.mark_paid, ) @@ -1441,9 +1366,15 @@ def __init__(self, invoices: AsyncInvoicesResource) -> None: self.retrieve = async_to_raw_response_wrapper( invoices.retrieve, ) + self.update = async_to_raw_response_wrapper( + invoices.update, + ) self.list = async_to_raw_response_wrapper( invoices.list, ) + self.delete = async_to_raw_response_wrapper( + invoices.delete, + ) self.mark_paid = async_to_raw_response_wrapper( invoices.mark_paid, ) @@ -1465,9 +1396,15 @@ def __init__(self, invoices: InvoicesResource) -> None: self.retrieve = to_streamed_response_wrapper( invoices.retrieve, ) + self.update = to_streamed_response_wrapper( + invoices.update, + ) self.list = to_streamed_response_wrapper( invoices.list, ) + self.delete = to_streamed_response_wrapper( + invoices.delete, + ) self.mark_paid = to_streamed_response_wrapper( invoices.mark_paid, ) @@ -1489,9 +1426,15 @@ def __init__(self, invoices: AsyncInvoicesResource) -> None: self.retrieve = async_to_streamed_response_wrapper( invoices.retrieve, ) + self.update = async_to_streamed_response_wrapper( + invoices.update, + ) self.list = async_to_streamed_response_wrapper( invoices.list, ) + self.delete = async_to_streamed_response_wrapper( + invoices.delete, + ) self.mark_paid = async_to_streamed_response_wrapper( invoices.mark_paid, ) diff --git a/src/whop_sdk/types/__init__.py b/src/whop_sdk/types/__init__.py index 95e067c..cd41bef 100644 --- a/src/whop_sdk/types/__init__.py +++ b/src/whop_sdk/types/__init__.py @@ -82,12 +82,14 @@ from .card_brands import CardBrands as CardBrands from .lesson_types import LessonTypes as LessonTypes from .setup_intent import SetupIntent as SetupIntent +from .checkout_font import CheckoutFont as CheckoutFont from .refund_status import RefundStatus as RefundStatus from .review_status import ReviewStatus as ReviewStatus from .upload_status import UploadStatus as UploadStatus from .webhook_event import WebhookEvent as WebhookEvent from .cancel_options import CancelOptions as CancelOptions from .checkout_modes import CheckoutModes as CheckoutModes +from .checkout_shape import CheckoutShape as CheckoutShape from .course_chapter import CourseChapter as CourseChapter from .promo_duration import PromoDuration as PromoDuration from .app_list_params import AppListParams as AppListParams @@ -164,6 +166,7 @@ from .dispute_list_response import DisputeListResponse as DisputeListResponse from .dm_member_list_params import DmMemberListParams as DmMemberListParams from .invoice_create_params import InvoiceCreateParams as InvoiceCreateParams +from .invoice_update_params import InvoiceUpdateParams as InvoiceUpdateParams from .invoice_void_response import InvoiceVoidResponse as InvoiceVoidResponse from .message_create_params import MessageCreateParams as MessageCreateParams from .message_list_response import MessageListResponse as MessageListResponse @@ -204,6 +207,7 @@ from .dm_member_create_params import DmMemberCreateParams as DmMemberCreateParams from .dm_member_list_response import DmMemberListResponse as DmMemberListResponse from .dm_member_update_params import DmMemberUpdateParams as DmMemberUpdateParams +from .invoice_delete_response import InvoiceDeleteResponse as InvoiceDeleteResponse from .membership_pause_params import MembershipPauseParams as MembershipPauseParams from .message_delete_response import MessageDeleteResponse as MessageDeleteResponse from .product_delete_response import ProductDeleteResponse as ProductDeleteResponse diff --git a/src/whop_sdk/types/checkout_configuration_create_params.py b/src/whop_sdk/types/checkout_configuration_create_params.py index ba31559..68a873e 100644 --- a/src/whop_sdk/types/checkout_configuration_create_params.py +++ b/src/whop_sdk/types/checkout_configuration_create_params.py @@ -5,6 +5,8 @@ from typing import Dict, List, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict +from .checkout_font import CheckoutFont +from .checkout_shape import CheckoutShape from .shared.currency import Currency from .shared.tax_type import TaxType from .shared.plan_type import PlanType @@ -290,13 +292,13 @@ class CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling(TypedDict, to Overrides plan and company defaults. """ - border_style: Optional[Literal["rounded", "pill", "rectangular"]] + border_style: Optional[CheckoutShape] """The different border-radius styles available for checkout pages.""" button_color: Optional[str] """A hex color code for the button color (e.g. #FF5733).""" - font_family: Optional[Literal["system", "roboto", "open_sans"]] + font_family: Optional[CheckoutFont] """The different font families available for checkout pages.""" @@ -372,13 +374,13 @@ class CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling(TypedDict, Overrides plan and company defaults. """ - border_style: Optional[Literal["rounded", "pill", "rectangular"]] + border_style: Optional[CheckoutShape] """The different border-radius styles available for checkout pages.""" button_color: Optional[str] """A hex color code for the button color (e.g. #FF5733).""" - font_family: Optional[Literal["system", "roboto", "open_sans"]] + font_family: Optional[CheckoutFont] """The different font families available for checkout pages.""" @@ -451,13 +453,13 @@ class CreateCheckoutSessionInputModeSetupCheckoutStyling(TypedDict, total=False) Overrides plan and company defaults. """ - border_style: Optional[Literal["rounded", "pill", "rectangular"]] + border_style: Optional[CheckoutShape] """The different border-radius styles available for checkout pages.""" button_color: Optional[str] """A hex color code for the button color (e.g. #FF5733).""" - font_family: Optional[Literal["system", "roboto", "open_sans"]] + font_family: Optional[CheckoutFont] """The different font families available for checkout pages.""" diff --git a/src/whop_sdk/types/checkout_font.py b/src/whop_sdk/types/checkout_font.py new file mode 100644 index 0000000..deaa4f2 --- /dev/null +++ b/src/whop_sdk/types/checkout_font.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["CheckoutFont"] + +CheckoutFont: TypeAlias = Literal["system", "roboto", "open_sans"] diff --git a/src/whop_sdk/types/checkout_shape.py b/src/whop_sdk/types/checkout_shape.py new file mode 100644 index 0000000..6e00761 --- /dev/null +++ b/src/whop_sdk/types/checkout_shape.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["CheckoutShape"] + +CheckoutShape: TypeAlias = Literal["rounded", "pill", "rectangular"] diff --git a/src/whop_sdk/types/invoice_create_params.py b/src/whop_sdk/types/invoice_create_params.py index a197501..1ae0222 100644 --- a/src/whop_sdk/types/invoice_create_params.py +++ b/src/whop_sdk/types/invoice_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Union, Iterable, Optional +from typing import List, Union, Iterable, Optional from datetime import datetime from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict @@ -10,37 +10,29 @@ from .shared.plan_type import PlanType from .shared.visibility import Visibility from .tax_identifier_type import TaxIdentifierType +from .payment_method_types import PaymentMethodTypes from .shared.release_method import ReleaseMethod from .shared.collection_method import CollectionMethod __all__ = [ "InvoiceCreateParams", - "CreateInvoiceInputWithProductAndMemberID", - "CreateInvoiceInputWithProductAndMemberIDPlan", - "CreateInvoiceInputWithProductAndMemberIDPlanCustomField", - "CreateInvoiceInputWithProductAndMemberIDProduct", - "CreateInvoiceInputWithProductAndMemberIDBillingAddress", - "CreateInvoiceInputWithProductAndMemberIDLineItem", - "CreateInvoiceInputWithProductAndEmailAddress", - "CreateInvoiceInputWithProductAndEmailAddressPlan", - "CreateInvoiceInputWithProductAndEmailAddressPlanCustomField", - "CreateInvoiceInputWithProductAndEmailAddressProduct", - "CreateInvoiceInputWithProductAndEmailAddressBillingAddress", - "CreateInvoiceInputWithProductAndEmailAddressLineItem", - "CreateInvoiceInputWithProductIDAndMemberID", - "CreateInvoiceInputWithProductIDAndMemberIDPlan", - "CreateInvoiceInputWithProductIDAndMemberIDPlanCustomField", - "CreateInvoiceInputWithProductIDAndMemberIDLineItem", - "CreateInvoiceInputWithProductIDAndEmailAddress", - "CreateInvoiceInputWithProductIDAndEmailAddressPlan", - "CreateInvoiceInputWithProductIDAndEmailAddressPlanCustomField", - "CreateInvoiceInputWithProductIDAndMemberIDBillingAddress", - "CreateInvoiceInputWithProductIDAndEmailAddressBillingAddress", - "CreateInvoiceInputWithProductIDAndEmailAddressLineItem", + "CreateInvoiceInputWithProduct", + "CreateInvoiceInputWithProductPlan", + "CreateInvoiceInputWithProductPlanCustomField", + "CreateInvoiceInputWithProductPlanPaymentMethodConfiguration", + "CreateInvoiceInputWithProductProduct", + "CreateInvoiceInputWithProductBillingAddress", + "CreateInvoiceInputWithProductLineItem", + "CreateInvoiceInputWithProductID", + "CreateInvoiceInputWithProductIDPlan", + "CreateInvoiceInputWithProductIDPlanCustomField", + "CreateInvoiceInputWithProductIDPlanPaymentMethodConfiguration", + "CreateInvoiceInputWithProductIDBillingAddress", + "CreateInvoiceInputWithProductIDLineItem", ] -class CreateInvoiceInputWithProductAndMemberID(TypedDict, total=False): +class CreateInvoiceInputWithProduct(TypedDict, total=False): collection_method: Required[CollectionMethod] """How the invoice should be collected. @@ -51,22 +43,13 @@ class CreateInvoiceInputWithProductAndMemberID(TypedDict, total=False): company_id: Required[str] """The unique identifier of the company to create this invoice for.""" - due_date: Required[Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]] - """The date by which the invoice must be paid.""" - - member_id: Required[str] - """The unique identifier of an existing member to create this invoice for. - - If not provided, you must supply an email_address and customer_name. - """ - - plan: Required[CreateInvoiceInputWithProductAndMemberIDPlan] + plan: Required[CreateInvoiceInputWithProductPlan] """ The plan attributes defining the price, currency, and billing interval for this invoice. """ - product: Required[CreateInvoiceInputWithProductAndMemberIDProduct] + product: Required[CreateInvoiceInputWithProductProduct] """The properties of the product to create for this invoice. Provide this to create a new product inline. @@ -79,7 +62,7 @@ class CreateInvoiceInputWithProductAndMemberID(TypedDict, total=False): charge will be processed immediately. """ - billing_address: Optional[CreateInvoiceInputWithProductAndMemberIDBillingAddress] + billing_address: Optional[CreateInvoiceInputWithProductBillingAddress] """Inline billing address to create a new mailing address for this invoice. Cannot be used together with mailing_address_id. @@ -95,7 +78,20 @@ class CreateInvoiceInputWithProductAndMemberID(TypedDict, total=False): company. """ - line_items: Optional[Iterable[CreateInvoiceInputWithProductAndMemberIDLineItem]] + due_date: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """The date by which the invoice must be paid. + + Required unless save_as_draft is true. + """ + + email_address: Optional[str] + """The email address of the customer. + + Required when creating an invoice for a customer who is not yet a member of the + company. + """ + + line_items: Optional[Iterable[CreateInvoiceInputWithProductLineItem]] """Optional line items that break down the invoice total. When provided, the sum of (quantity \\** unit_price) for all items must equal the @@ -108,6 +104,12 @@ class CreateInvoiceInputWithProductAndMemberID(TypedDict, total=False): Cannot be used together with billing_address. """ + member_id: Optional[str] + """The unique identifier of an existing member to create this invoice for. + + If not provided, you must supply an email_address and customer_name. + """ + payment_method_id: Optional[str] """The unique identifier of the payment method to charge. @@ -120,8 +122,14 @@ class CreateInvoiceInputWithProductAndMemberID(TypedDict, total=False): If using charge_automatically, you must provide a payment_token. """ + save_as_draft: Optional[bool] + """When true, creates the invoice as a draft without sending or charging. + + Relaxes customer and due date requirements. + """ + -class CreateInvoiceInputWithProductAndMemberIDPlanCustomField(TypedDict, total=False): +class CreateInvoiceInputWithProductPlanCustomField(TypedDict, total=False): field_type: Required[Literal["text"]] """The type of the custom field.""" @@ -141,237 +149,35 @@ class CreateInvoiceInputWithProductAndMemberIDPlanCustomField(TypedDict, total=F """Whether or not the field is required.""" -class CreateInvoiceInputWithProductAndMemberIDPlan(TypedDict, total=False): - """ - The plan attributes defining the price, currency, and billing interval for this invoice. - """ - - billing_period: Optional[int] - """The interval in days at which the plan charges (renewal plans).""" - - custom_fields: Optional[Iterable[CreateInvoiceInputWithProductAndMemberIDPlanCustomField]] - """An array of custom field objects.""" - - description: Optional[str] - """The description of the plan.""" - - expiration_days: Optional[int] - """ - The number of days until the membership expires and revokes access (expiration - plans). For example, 365 for a one-year access period. - """ - - initial_price: Optional[float] - """An additional amount charged upon first purchase. - - Use only if a one time payment OR you want to charge an additional amount on top - of the renewal price. Provided as a number in the specified currency. Eg: 10.43 - for $10.43 - """ - - internal_notes: Optional[str] - """A personal description or notes section for the business.""" - - plan_type: Optional[PlanType] - """The type of plan that can be attached to a product""" - - release_method: Optional[ReleaseMethod] - """The methods of how a plan can be released.""" - - renewal_price: Optional[float] - """The amount the customer is charged every billing period. - - Use only if a recurring payment. Provided as a number in the specified currency. - Eg: 10.43 for $10.43 - """ - - stock: Optional[int] - """The number of units available for purchase.""" - - trial_period_days: Optional[int] - """The number of free trial days added before a renewal plan.""" - - unlimited_stock: Optional[bool] - """When true, the plan has unlimited stock (stock field is ignored). - - When false, purchases are limited by the stock field. - """ - - visibility: Optional[Visibility] - """Visibility of a resource""" - - -class CreateInvoiceInputWithProductAndMemberIDProduct(TypedDict, total=False): - """The properties of the product to create for this invoice. - - Provide this to create a new product inline. - """ - - title: Required[str] - """The title of the product.""" - - product_tax_code_id: Optional[str] - """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. - - Use charge_automatically to charge a stored payment method, or send_invoice to - email the customer. - """ - - company_id: Required[str] - """The unique identifier of the company to create this invoice for.""" - - due_date: Required[Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]] - """The date by which the invoice must be paid.""" - - email_address: Required[str] - """The email address of the customer. - - Required when creating an invoice for a customer who is not yet a member of the - company. - """ - - plan: Required[CreateInvoiceInputWithProductAndEmailAddressPlan] - """ - The plan attributes defining the price, currency, and billing interval for this - invoice. - """ - - product: Required[CreateInvoiceInputWithProductAndEmailAddressProduct] - """The properties of the product to create for this invoice. - - Provide this to create a new product inline. - """ - - automatically_finalizes_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] - """The date and time when the invoice will be automatically finalized and charged. - - Only valid when collection_method is charge_automatically. If not provided, the - charge will be processed immediately. - """ - - billing_address: Optional[CreateInvoiceInputWithProductAndEmailAddressBillingAddress] - """Inline billing address to create a new mailing address for this invoice. +class CreateInvoiceInputWithProductPlanPaymentMethodConfiguration(TypedDict, total=False): + """The explicit payment method configuration for the plan. - Cannot be used together with mailing_address_id. + If not provided, the platform or company's defaults will apply. """ - charge_buyer_fee: Optional[bool] - """Whether to charge the customer a buyer fee on this invoice.""" + disabled: Required[List[PaymentMethodTypes]] + """An array of payment method identifiers that are explicitly disabled. - customer_name: Optional[str] - """The name of the customer. - - Required when creating an invoice for a customer who is not yet a member of the - company. + Only applies if the include_platform_defaults is true. """ - line_items: Optional[Iterable[CreateInvoiceInputWithProductAndEmailAddressLineItem]] - """Optional line items that break down the invoice total. + enabled: Required[List[PaymentMethodTypes]] + """An array of payment method identifiers that are explicitly enabled. - When provided, the sum of (quantity \\** unit_price) for all items must equal the - plan price. + This means these payment methods will be shown on checkout. Example use case is + to only enable a specific payment method like cashapp, or extending the platform + defaults with additional methods. """ - 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. + include_platform_defaults: Required[bool] """ - - payment_method_id: Optional[str] - """The unique identifier of the payment method to charge. - - Required when collection_method is charge_automatically. + Whether Whop's platform default payment method enablement settings are included + in this configuration. The full list of default payment methods can be found in + the documentation at docs.whop.com/payments. """ - payment_token_id: Optional[str] - """The payment token ID to use for this invoice. - If using charge_automatically, you must provide a payment_token. - """ - - -class CreateInvoiceInputWithProductAndEmailAddressPlanCustomField(TypedDict, total=False): - field_type: Required[Literal["text"]] - """The type of the custom field.""" - - name: Required[str] - """The name of the custom field.""" - - id: Optional[str] - """The ID of the custom field (if being updated)""" - - order: Optional[int] - """The order of the field.""" - - placeholder: Optional[str] - """The placeholder value of the field.""" - - required: Optional[bool] - """Whether or not the field is required.""" - - -class CreateInvoiceInputWithProductAndEmailAddressPlan(TypedDict, total=False): +class CreateInvoiceInputWithProductPlan(TypedDict, total=False): """ The plan attributes defining the price, currency, and billing interval for this invoice. """ @@ -379,7 +185,7 @@ class CreateInvoiceInputWithProductAndEmailAddressPlan(TypedDict, total=False): billing_period: Optional[int] """The interval in days at which the plan charges (renewal plans).""" - custom_fields: Optional[Iterable[CreateInvoiceInputWithProductAndEmailAddressPlanCustomField]] + custom_fields: Optional[Iterable[CreateInvoiceInputWithProductPlanCustomField]] """An array of custom field objects.""" description: Optional[str] @@ -402,6 +208,15 @@ class CreateInvoiceInputWithProductAndEmailAddressPlan(TypedDict, total=False): internal_notes: Optional[str] """A personal description or notes section for the business.""" + legacy_payment_method_controls: Optional[bool] + """Whether this plan uses legacy payment method controls""" + + payment_method_configuration: Optional[CreateInvoiceInputWithProductPlanPaymentMethodConfiguration] + """The explicit payment method configuration for the plan. + + If not provided, the platform or company's defaults will apply. + """ + plan_type: Optional[PlanType] """The type of plan that can be attached to a product""" @@ -431,7 +246,7 @@ class CreateInvoiceInputWithProductAndEmailAddressPlan(TypedDict, total=False): """Visibility of a resource""" -class CreateInvoiceInputWithProductAndEmailAddressProduct(TypedDict, total=False): +class CreateInvoiceInputWithProductProduct(TypedDict, total=False): """The properties of the product to create for this invoice. Provide this to create a new product inline. @@ -444,7 +259,7 @@ class CreateInvoiceInputWithProductAndEmailAddressProduct(TypedDict, total=False """The ID of the product tax code to apply to this product.""" -class CreateInvoiceInputWithProductAndEmailAddressBillingAddress(TypedDict, total=False): +class CreateInvoiceInputWithProductBillingAddress(TypedDict, total=False): """Inline billing address to create a new mailing address for this invoice. Cannot be used together with mailing_address_id. @@ -481,7 +296,7 @@ class CreateInvoiceInputWithProductAndEmailAddressBillingAddress(TypedDict, tota """The value of the tax identifier.""" -class CreateInvoiceInputWithProductAndEmailAddressLineItem(TypedDict, total=False): +class CreateInvoiceInputWithProductLineItem(TypedDict, total=False): """ A single line item to include on the invoice, with a label, quantity, and unit price. """ @@ -499,7 +314,7 @@ class CreateInvoiceInputWithProductAndEmailAddressLineItem(TypedDict, total=Fals """The quantity of this line item. Defaults to 1.""" -class CreateInvoiceInputWithProductIDAndMemberID(TypedDict, total=False): +class CreateInvoiceInputWithProductID(TypedDict, total=False): collection_method: Required[CollectionMethod] """How the invoice should be collected. @@ -510,16 +325,7 @@ class CreateInvoiceInputWithProductIDAndMemberID(TypedDict, total=False): company_id: Required[str] """The unique identifier of the company to create this invoice for.""" - due_date: Required[Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]] - """The date by which the invoice must be paid.""" - - member_id: Required[str] - """The unique identifier of an existing member to create this invoice for. - - If not provided, you must supply an email_address and customer_name. - """ - - plan: Required[CreateInvoiceInputWithProductIDAndMemberIDPlan] + plan: Required[CreateInvoiceInputWithProductIDPlan] """ The plan attributes defining the price, currency, and billing interval for this invoice. @@ -535,7 +341,7 @@ class CreateInvoiceInputWithProductIDAndMemberID(TypedDict, total=False): charge will be processed immediately. """ - billing_address: Optional[CreateInvoiceInputWithProductIDAndMemberIDBillingAddress] + billing_address: Optional[CreateInvoiceInputWithProductIDBillingAddress] """Inline billing address to create a new mailing address for this invoice. Cannot be used together with mailing_address_id. @@ -551,7 +357,20 @@ class CreateInvoiceInputWithProductIDAndMemberID(TypedDict, total=False): company. """ - line_items: Optional[Iterable[CreateInvoiceInputWithProductIDAndMemberIDLineItem]] + due_date: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """The date by which the invoice must be paid. + + Required unless save_as_draft is true. + """ + + email_address: Optional[str] + """The email address of the customer. + + Required when creating an invoice for a customer who is not yet a member of the + company. + """ + + line_items: Optional[Iterable[CreateInvoiceInputWithProductIDLineItem]] """Optional line items that break down the invoice total. When provided, the sum of (quantity \\** unit_price) for all items must equal the @@ -564,6 +383,12 @@ class CreateInvoiceInputWithProductIDAndMemberID(TypedDict, total=False): Cannot be used together with billing_address. """ + member_id: Optional[str] + """The unique identifier of an existing member to create this invoice for. + + If not provided, you must supply an email_address and customer_name. + """ + payment_method_id: Optional[str] """The unique identifier of the payment method to charge. @@ -576,8 +401,14 @@ class CreateInvoiceInputWithProductIDAndMemberID(TypedDict, total=False): If using charge_automatically, you must provide a payment_token. """ + save_as_draft: Optional[bool] + """When true, creates the invoice as a draft without sending or charging. + + Relaxes customer and due date requirements. + """ + -class CreateInvoiceInputWithProductIDAndMemberIDPlanCustomField(TypedDict, total=False): +class CreateInvoiceInputWithProductIDPlanCustomField(TypedDict, total=False): field_type: Required[Literal["text"]] """The type of the custom field.""" @@ -597,221 +428,35 @@ class CreateInvoiceInputWithProductIDAndMemberIDPlanCustomField(TypedDict, total """Whether or not the field is required.""" -class CreateInvoiceInputWithProductIDAndMemberIDPlan(TypedDict, total=False): - """ - The plan attributes defining the price, currency, and billing interval for this invoice. - """ - - billing_period: Optional[int] - """The interval in days at which the plan charges (renewal plans).""" - - custom_fields: Optional[Iterable[CreateInvoiceInputWithProductIDAndMemberIDPlanCustomField]] - """An array of custom field objects.""" - - description: Optional[str] - """The description of the plan.""" +class CreateInvoiceInputWithProductIDPlanPaymentMethodConfiguration(TypedDict, total=False): + """The explicit payment method configuration for the plan. - expiration_days: Optional[int] - """ - The number of days until the membership expires and revokes access (expiration - plans). For example, 365 for a one-year access period. + If not provided, the platform or company's defaults will apply. """ - initial_price: Optional[float] - """An additional amount charged upon first purchase. + disabled: Required[List[PaymentMethodTypes]] + """An array of payment method identifiers that are explicitly disabled. - Use only if a one time payment OR you want to charge an additional amount on top - of the renewal price. Provided as a number in the specified currency. Eg: 10.43 - for $10.43 + Only applies if the include_platform_defaults is true. """ - internal_notes: Optional[str] - """A personal description or notes section for the business.""" - - plan_type: Optional[PlanType] - """The type of plan that can be attached to a product""" - - release_method: Optional[ReleaseMethod] - """The methods of how a plan can be released.""" - - renewal_price: Optional[float] - """The amount the customer is charged every billing period. + enabled: Required[List[PaymentMethodTypes]] + """An array of payment method identifiers that are explicitly enabled. - Use only if a recurring payment. Provided as a number in the specified currency. - Eg: 10.43 for $10.43 + This means these payment methods will be shown on checkout. Example use case is + to only enable a specific payment method like cashapp, or extending the platform + defaults with additional methods. """ - stock: Optional[int] - """The number of units available for purchase.""" - - trial_period_days: Optional[int] - """The number of free trial days added before a renewal plan.""" - - unlimited_stock: Optional[bool] - """When true, the plan has unlimited stock (stock field is ignored). - - When false, purchases are limited by the stock field. + include_platform_defaults: Required[bool] """ - - visibility: Optional[Visibility] - """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. + Whether Whop's platform default payment method enablement settings are included + in this configuration. The full list of default payment methods can be found in + the documentation at docs.whop.com/payments. """ - 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. - - Use charge_automatically to charge a stored payment method, or send_invoice to - email the customer. - """ - - company_id: Required[str] - """The unique identifier of the company to create this invoice for.""" - - due_date: Required[Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]] - """The date by which the invoice must be paid.""" - - email_address: Required[str] - """The email address of the customer. - - Required when creating an invoice for a customer who is not yet a member of the - company. - """ - - plan: Required[CreateInvoiceInputWithProductIDAndEmailAddressPlan] - """ - The plan attributes defining the price, currency, and billing interval for this - invoice. - """ - - product_id: Required[str] - """The unique identifier of an existing product to create this invoice for.""" - - automatically_finalizes_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] - """The date and time when the invoice will be automatically finalized and charged. - - Only valid when collection_method is charge_automatically. If not provided, the - 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.""" - - customer_name: Optional[str] - """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[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. - - Required when collection_method is charge_automatically. - """ - - payment_token_id: Optional[str] - """The payment token ID to use for this invoice. - - If using charge_automatically, you must provide a payment_token. - """ - - -class CreateInvoiceInputWithProductIDAndEmailAddressPlanCustomField(TypedDict, total=False): - field_type: Required[Literal["text"]] - """The type of the custom field.""" - - name: Required[str] - """The name of the custom field.""" - - id: Optional[str] - """The ID of the custom field (if being updated)""" - - order: Optional[int] - """The order of the field.""" - - placeholder: Optional[str] - """The placeholder value of the field.""" - - required: Optional[bool] - """Whether or not the field is required.""" - - -class CreateInvoiceInputWithProductIDAndEmailAddressPlan(TypedDict, total=False): +class CreateInvoiceInputWithProductIDPlan(TypedDict, total=False): """ The plan attributes defining the price, currency, and billing interval for this invoice. """ @@ -819,7 +464,7 @@ class CreateInvoiceInputWithProductIDAndEmailAddressPlan(TypedDict, total=False) billing_period: Optional[int] """The interval in days at which the plan charges (renewal plans).""" - custom_fields: Optional[Iterable[CreateInvoiceInputWithProductIDAndEmailAddressPlanCustomField]] + custom_fields: Optional[Iterable[CreateInvoiceInputWithProductIDPlanCustomField]] """An array of custom field objects.""" description: Optional[str] @@ -842,6 +487,15 @@ class CreateInvoiceInputWithProductIDAndEmailAddressPlan(TypedDict, total=False) internal_notes: Optional[str] """A personal description or notes section for the business.""" + legacy_payment_method_controls: Optional[bool] + """Whether this plan uses legacy payment method controls""" + + payment_method_configuration: Optional[CreateInvoiceInputWithProductIDPlanPaymentMethodConfiguration] + """The explicit payment method configuration for the plan. + + If not provided, the platform or company's defaults will apply. + """ + plan_type: Optional[PlanType] """The type of plan that can be attached to a product""" @@ -871,7 +525,7 @@ class CreateInvoiceInputWithProductIDAndEmailAddressPlan(TypedDict, total=False) """Visibility of a resource""" -class CreateInvoiceInputWithProductIDAndEmailAddressBillingAddress(TypedDict, total=False): +class CreateInvoiceInputWithProductIDBillingAddress(TypedDict, total=False): """Inline billing address to create a new mailing address for this invoice. Cannot be used together with mailing_address_id. @@ -908,7 +562,7 @@ class CreateInvoiceInputWithProductIDAndEmailAddressBillingAddress(TypedDict, to """The value of the tax identifier.""" -class CreateInvoiceInputWithProductIDAndEmailAddressLineItem(TypedDict, total=False): +class CreateInvoiceInputWithProductIDLineItem(TypedDict, total=False): """ A single line item to include on the invoice, with a label, quantity, and unit price. """ @@ -926,9 +580,4 @@ class CreateInvoiceInputWithProductIDAndEmailAddressLineItem(TypedDict, total=Fa """The quantity of this line item. Defaults to 1.""" -InvoiceCreateParams: TypeAlias = Union[ - CreateInvoiceInputWithProductAndMemberID, - CreateInvoiceInputWithProductAndEmailAddress, - CreateInvoiceInputWithProductIDAndMemberID, - CreateInvoiceInputWithProductIDAndEmailAddress, -] +InvoiceCreateParams: TypeAlias = Union[CreateInvoiceInputWithProduct, CreateInvoiceInputWithProductID] diff --git a/src/whop_sdk/types/invoice_delete_response.py b/src/whop_sdk/types/invoice_delete_response.py new file mode 100644 index 0000000..0a6112b --- /dev/null +++ b/src/whop_sdk/types/invoice_delete_response.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import TypeAlias + +__all__ = ["InvoiceDeleteResponse"] + +InvoiceDeleteResponse: TypeAlias = bool diff --git a/src/whop_sdk/types/invoice_update_params.py b/src/whop_sdk/types/invoice_update_params.py new file mode 100644 index 0000000..bbd273c --- /dev/null +++ b/src/whop_sdk/types/invoice_update_params.py @@ -0,0 +1,229 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union, Iterable, Optional +from datetime import datetime +from typing_extensions import Literal, Required, Annotated, TypedDict + +from .._utils import PropertyInfo +from .shared.plan_type import PlanType +from .shared.visibility import Visibility +from .tax_identifier_type import TaxIdentifierType +from .payment_method_types import PaymentMethodTypes +from .shared.release_method import ReleaseMethod +from .shared.collection_method import CollectionMethod + +__all__ = [ + "InvoiceUpdateParams", + "BillingAddress", + "LineItem", + "Plan", + "PlanCustomField", + "PlanPaymentMethodConfiguration", +] + + +class InvoiceUpdateParams(TypedDict, total=False): + automatically_finalizes_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """The date and time when the invoice will be automatically finalized and charged.""" + + billing_address: Optional[BillingAddress] + """Inline billing address to create or update a mailing address for this invoice.""" + + charge_buyer_fee: Optional[bool] + """Whether to charge the customer a buyer fee on this invoice.""" + + collection_method: Optional[CollectionMethod] + """The method of collection for an invoice.""" + + customer_name: Optional[str] + """The name of the customer.""" + + due_date: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """The date by which the invoice must be paid.""" + + email_address: Optional[str] + """The email address of the customer.""" + + line_items: Optional[Iterable[LineItem]] + """Line items that break down the invoice total.""" + + mailing_address_id: Optional[str] + """The unique identifier of an existing mailing address to attach.""" + + member_id: Optional[str] + """The unique identifier of a member to assign as the customer.""" + + payment_method_id: Optional[str] + """The unique identifier of the payment method to charge.""" + + plan: Optional[Plan] + """Updated plan attributes.""" + + +class BillingAddress(TypedDict, total=False): + """Inline billing address to create or update a mailing address for this invoice.""" + + 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 LineItem(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 PlanCustomField(TypedDict, total=False): + field_type: Required[Literal["text"]] + """The type of the custom field.""" + + name: Required[str] + """The name of the custom field.""" + + id: Optional[str] + """The ID of the custom field (if being updated)""" + + order: Optional[int] + """The order of the field.""" + + placeholder: Optional[str] + """The placeholder value of the field.""" + + required: Optional[bool] + """Whether or not the field is required.""" + + +class PlanPaymentMethodConfiguration(TypedDict, total=False): + """The explicit payment method configuration for the plan. + + If not provided, the platform or company's defaults will apply. + """ + + disabled: Required[List[PaymentMethodTypes]] + """An array of payment method identifiers that are explicitly disabled. + + Only applies if the include_platform_defaults is true. + """ + + enabled: Required[List[PaymentMethodTypes]] + """An array of payment method identifiers that are explicitly enabled. + + This means these payment methods will be shown on checkout. Example use case is + to only enable a specific payment method like cashapp, or extending the platform + defaults with additional methods. + """ + + include_platform_defaults: Required[bool] + """ + Whether Whop's platform default payment method enablement settings are included + in this configuration. The full list of default payment methods can be found in + the documentation at docs.whop.com/payments. + """ + + +class Plan(TypedDict, total=False): + """Updated plan attributes.""" + + billing_period: Optional[int] + """The interval in days at which the plan charges (renewal plans).""" + + custom_fields: Optional[Iterable[PlanCustomField]] + """An array of custom field objects.""" + + description: Optional[str] + """The description of the plan.""" + + expiration_days: Optional[int] + """ + The number of days until the membership expires and revokes access (expiration + plans). For example, 365 for a one-year access period. + """ + + initial_price: Optional[float] + """An additional amount charged upon first purchase. + + Use only if a one time payment OR you want to charge an additional amount on top + of the renewal price. Provided as a number in the specified currency. Eg: 10.43 + for $10.43 + """ + + internal_notes: Optional[str] + """A personal description or notes section for the business.""" + + legacy_payment_method_controls: Optional[bool] + """Whether this plan uses legacy payment method controls""" + + payment_method_configuration: Optional[PlanPaymentMethodConfiguration] + """The explicit payment method configuration for the plan. + + If not provided, the platform or company's defaults will apply. + """ + + plan_type: Optional[PlanType] + """The type of plan that can be attached to a product""" + + release_method: Optional[ReleaseMethod] + """The methods of how a plan can be released.""" + + renewal_price: Optional[float] + """The amount the customer is charged every billing period. + + Use only if a recurring payment. Provided as a number in the specified currency. + Eg: 10.43 for $10.43 + """ + + stock: Optional[int] + """The number of units available for purchase.""" + + trial_period_days: Optional[int] + """The number of free trial days added before a renewal plan.""" + + unlimited_stock: Optional[bool] + """When true, the plan has unlimited stock (stock field is ignored). + + When false, purchases are limited by the stock field. + """ + + visibility: Optional[Visibility] + """Visibility of a resource""" diff --git a/src/whop_sdk/types/membership_list_response.py b/src/whop_sdk/types/membership_list_response.py index cd992e2..13586e5 100644 --- a/src/whop_sdk/types/membership_list_response.py +++ b/src/whop_sdk/types/membership_list_response.py @@ -148,7 +148,7 @@ class MembershipListResponse(BaseModel): Null if the member record has not been created yet. """ - metadata: Dict[str, object] + metadata: Optional[Dict[str, object]] = None """ Custom key-value pairs for the membership (commonly used for software licensing, e.g., HWID). Max 50 keys, 500 chars per key, 5000 chars per value. diff --git a/src/whop_sdk/types/payment_method_types.py b/src/whop_sdk/types/payment_method_types.py index 526c34f..d039c9e 100644 --- a/src/whop_sdk/types/payment_method_types.py +++ b/src/whop_sdk/types/payment_method_types.py @@ -15,6 +15,7 @@ "apple_pay", "au_becs_debit", "bacs_debit", + "bancolombia", "bancontact", "billie", "bizum", @@ -29,6 +30,7 @@ "custom", "customer_balance", "demo_pay", + "efecty", "eps", "eu_bank_transfer", "fpx", @@ -47,10 +49,12 @@ "kriya", "link", "mb_way", + "mercado_pago", "mobilepay", "mondu", "multibanco", "naver_pay", + "nequi", "netbanking", "ng_bank", "ng_bank_transfer", @@ -61,6 +65,7 @@ "nz_bank_account", "oxxo", "p24", + "pse", "pay_by_bank", "payco", "paynow", @@ -83,6 +88,7 @@ "shopeepay", "sofort", "south_korea_market", + "spei", "splitit", "sunbit", "swish", diff --git a/src/whop_sdk/types/payment_provider.py b/src/whop_sdk/types/payment_provider.py index 6d8567f..506f027 100644 --- a/src/whop_sdk/types/payment_provider.py +++ b/src/whop_sdk/types/payment_provider.py @@ -19,4 +19,5 @@ "airwallex", "coinflow", "sequra", + "dlocal", ] diff --git a/src/whop_sdk/types/plan_create_params.py b/src/whop_sdk/types/plan_create_params.py index aebe213..d22e29e 100644 --- a/src/whop_sdk/types/plan_create_params.py +++ b/src/whop_sdk/types/plan_create_params.py @@ -5,6 +5,8 @@ from typing import List, Iterable, Optional from typing_extensions import Literal, Required, TypedDict +from .checkout_font import CheckoutFont +from .checkout_shape import CheckoutShape from .shared.currency import Currency from .shared.tax_type import TaxType from .shared.plan_type import PlanType @@ -121,13 +123,13 @@ class CheckoutStyling(TypedDict, total=False): Pass null to inherit from the company default. """ - border_style: Optional[Literal["rounded", "pill", "rectangular"]] + border_style: Optional[CheckoutShape] """The different border-radius styles available for checkout pages.""" button_color: Optional[str] """A hex color code for the button color (e.g. #FF5733).""" - font_family: Optional[Literal["system", "roboto", "open_sans"]] + font_family: Optional[CheckoutFont] """The different font families available for checkout pages.""" diff --git a/src/whop_sdk/types/plan_update_params.py b/src/whop_sdk/types/plan_update_params.py index d98f100..240f022 100644 --- a/src/whop_sdk/types/plan_update_params.py +++ b/src/whop_sdk/types/plan_update_params.py @@ -5,6 +5,8 @@ from typing import List, Iterable, Optional from typing_extensions import Literal, Required, TypedDict +from .checkout_font import CheckoutFont +from .checkout_shape import CheckoutShape from .shared.currency import Currency from .shared.tax_type import TaxType from .shared.visibility import Visibility @@ -114,13 +116,13 @@ class CheckoutStyling(TypedDict, total=False): Pass null to remove all overrides and inherit from the company default. """ - border_style: Optional[Literal["rounded", "pill", "rectangular"]] + border_style: Optional[CheckoutShape] """The different border-radius styles available for checkout pages.""" button_color: Optional[str] """A hex color code for the button color (e.g. #FF5733).""" - font_family: Optional[Literal["system", "roboto", "open_sans"]] + font_family: Optional[CheckoutFont] """The different font families available for checkout pages.""" diff --git a/src/whop_sdk/types/shared/membership.py b/src/whop_sdk/types/shared/membership.py index f144309..ac7d285 100644 --- a/src/whop_sdk/types/shared/membership.py +++ b/src/whop_sdk/types/shared/membership.py @@ -167,7 +167,7 @@ class Membership(BaseModel): Null if the member record has not been created yet. """ - metadata: Dict[str, object] + metadata: Optional[Dict[str, object]] = None """ Custom key-value pairs for the membership (commonly used for software licensing, e.g., HWID). Max 50 keys, 500 chars per key, 5000 chars per value. diff --git a/tests/api_resources/test_invoices.py b/tests/api_resources/test_invoices.py index 97377e3..2130e40 100644 --- a/tests/api_resources/test_invoices.py +++ b/tests/api_resources/test_invoices.py @@ -11,6 +11,7 @@ from tests.utils import assert_matches_type from whop_sdk.types import ( InvoiceVoidResponse, + InvoiceDeleteResponse, InvoiceMarkPaidResponse, InvoiceMarkUncollectibleResponse, ) @@ -24,27 +25,12 @@ class TestInvoices: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_create_overload_1(self, client: Whop) -> None: - invoice = client.invoices.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", - plan={}, - product={"title": "title"}, - ) - assert_matches_type(Invoice, invoice, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_create_with_all_params_overload_1(self, client: Whop) -> None: invoice = client.invoices.create( collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", plan={ "billing_period": 42, "custom_fields": [ @@ -88,6 +74,8 @@ def test_method_create_with_all_params_overload_1(self, client: Whop) -> None: }, charge_buyer_fee=True, customer_name="customer_name", + due_date=parse_datetime("2023-12-01T05:00:00.401Z"), + email_address="email_address", line_items=[ { "label": "label", @@ -96,57 +84,10 @@ def test_method_create_with_all_params_overload_1(self, client: Whop) -> None: } ], mailing_address_id="ma_xxxxxxxxxxxxxxx", + member_id="mber_xxxxxxxxxxxxx", payment_method_id="pmt_xxxxxxxxxxxxxx", payment_token_id="payt_xxxxxxxxxxxxx", - ) - assert_matches_type(Invoice, invoice, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_create_overload_1(self, client: Whop) -> None: - response = client.invoices.with_raw_response.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", - plan={}, - product={"title": "title"}, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - invoice = response.parse() - assert_matches_type(Invoice, invoice, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_create_overload_1(self, client: Whop) -> None: - with client.invoices.with_streaming_response.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", - plan={}, - product={"title": "title"}, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - invoice = response.parse() - assert_matches_type(Invoice, invoice, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_create_overload_2(self, client: Whop) -> None: - invoice = client.invoices.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", - plan={}, - product={"title": "title"}, + save_as_draft=True, ) assert_matches_type(Invoice, invoice, path=["response"]) @@ -156,8 +97,6 @@ def test_method_create_with_all_params_overload_2(self, client: Whop) -> None: invoice = client.invoices.create( collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", plan={ "billing_period": 42, "custom_fields": [ @@ -182,10 +121,7 @@ def test_method_create_with_all_params_overload_2(self, client: Whop) -> None: "unlimited_stock": True, "visibility": "visible", }, - product={ - "title": "title", - "product_tax_code_id": "ptc_xxxxxxxxxxxxxx", - }, + product_id="prod_xxxxxxxxxxxxx", automatically_finalizes_at=parse_datetime("2023-12-01T05:00:00.401Z"), billing_address={ "city": "city", @@ -201,6 +137,8 @@ def test_method_create_with_all_params_overload_2(self, client: Whop) -> None: }, charge_buyer_fee=True, customer_name="customer_name", + due_date=parse_datetime("2023-12-01T05:00:00.401Z"), + email_address="email_address", line_items=[ { "label": "label", @@ -209,57 +147,10 @@ def test_method_create_with_all_params_overload_2(self, client: Whop) -> None: } ], mailing_address_id="ma_xxxxxxxxxxxxxxx", + member_id="mber_xxxxxxxxxxxxx", payment_method_id="pmt_xxxxxxxxxxxxxx", payment_token_id="payt_xxxxxxxxxxxxx", - ) - assert_matches_type(Invoice, invoice, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_create_overload_2(self, client: Whop) -> None: - response = client.invoices.with_raw_response.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", - plan={}, - product={"title": "title"}, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - invoice = response.parse() - assert_matches_type(Invoice, invoice, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_create_overload_2(self, client: Whop) -> None: - with client.invoices.with_streaming_response.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", - plan={}, - product={"title": "title"}, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - invoice = response.parse() - assert_matches_type(Invoice, invoice, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_create_overload_3(self, client: Whop) -> None: - invoice = client.invoices.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", - plan={}, - product_id="prod_xxxxxxxxxxxxx", + save_as_draft=True, ) assert_matches_type(Invoice, invoice, path=["response"]) @@ -324,55 +215,6 @@ def test_method_create_with_all_params_overload_3(self, client: Whop) -> None: ) assert_matches_type(Invoice, invoice, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_create_overload_3(self, client: Whop) -> None: - response = client.invoices.with_raw_response.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", - plan={}, - product_id="prod_xxxxxxxxxxxxx", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - invoice = response.parse() - assert_matches_type(Invoice, invoice, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_create_overload_3(self, client: Whop) -> None: - with client.invoices.with_streaming_response.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", - plan={}, - product_id="prod_xxxxxxxxxxxxx", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - invoice = response.parse() - assert_matches_type(Invoice, invoice, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_create_overload_4(self, client: Whop) -> None: - invoice = client.invoices.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", - plan={}, - product_id="prod_xxxxxxxxxxxxx", - ) - assert_matches_type(Invoice, invoice, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_create_with_all_params_overload_4(self, client: Whop) -> None: @@ -434,42 +276,6 @@ def test_method_create_with_all_params_overload_4(self, client: Whop) -> None: ) assert_matches_type(Invoice, invoice, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_create_overload_4(self, client: Whop) -> None: - response = client.invoices.with_raw_response.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", - plan={}, - product_id="prod_xxxxxxxxxxxxx", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - invoice = response.parse() - assert_matches_type(Invoice, invoice, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_create_overload_4(self, client: Whop) -> None: - with client.invoices.with_streaming_response.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", - plan={}, - product_id="prod_xxxxxxxxxxxxx", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - invoice = response.parse() - assert_matches_type(Invoice, invoice, path=["response"]) - - assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_retrieve(self, client: Whop) -> None: @@ -553,60 +359,296 @@ def test_raw_response_list(self, client: Whop) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_streaming_response_list(self, client: Whop) -> None: - with client.invoices.with_streaming_response.list( + def test_method_create_overload_1(self, client: Whop) -> None: + invoice = client.invoices.create( + collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - invoice = response.parse() - assert_matches_type(SyncCursorPage[InvoiceListItem], invoice, path=["response"]) - - 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", + plan={}, + product={"title": "title"}, ) - assert_matches_type(InvoiceMarkPaidResponse, invoice, path=["response"]) + assert_matches_type(Invoice, 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", + def test_raw_response_create_overload_1(self, client: Whop) -> None: + response = client.invoices.with_raw_response.create( + collection_method="send_invoice", + company_id="biz_xxxxxxxxxxxxxx", + plan={}, + product={"title": "title"}, ) 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"]) + assert_matches_type(Invoice, 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", + def test_streaming_response_create_overload_1(self, client: Whop) -> None: + with client.invoices.with_streaming_response.create( + collection_method="send_invoice", + company_id="biz_xxxxxxxxxxxxxx", + plan={}, + product={"title": "title"}, ) 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_matches_type(Invoice, 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( - "", - ) - + def test_method_create_overload_2(self, client: Whop) -> None: + invoice = client.invoices.create( + collection_method="send_invoice", + company_id="biz_xxxxxxxxxxxxxx", + plan={}, + product_id="prod_xxxxxxxxxxxxx", + ) + assert_matches_type(Invoice, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create_overload_2(self, client: Whop) -> None: + response = client.invoices.with_raw_response.create( + collection_method="send_invoice", + company_id="biz_xxxxxxxxxxxxxx", + plan={}, + product_id="prod_xxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + invoice = response.parse() + assert_matches_type(Invoice, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create_overload_2(self, client: Whop) -> None: + with client.invoices.with_streaming_response.create( + collection_method="send_invoice", + company_id="biz_xxxxxxxxxxxxxx", + plan={}, + product_id="prod_xxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + invoice = response.parse() + assert_matches_type(Invoice, invoice, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update(self, client: Whop) -> None: + invoice = client.invoices.update( + id="inv_xxxxxxxxxxxxxx", + ) + assert_matches_type(Invoice, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: Whop) -> None: + invoice = client.invoices.update( + id="inv_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, + collection_method="send_invoice", + customer_name="customer_name", + due_date=parse_datetime("2023-12-01T05:00:00.401Z"), + email_address="email_address", + line_items=[ + { + "label": "label", + "unit_price": 6.9, + "quantity": 6.9, + } + ], + mailing_address_id="ma_xxxxxxxxxxxxxxx", + member_id="mber_xxxxxxxxxxxxx", + payment_method_id="pmt_xxxxxxxxxxxxxx", + plan={ + "billing_period": 42, + "custom_fields": [ + { + "field_type": "text", + "name": "name", + "id": "id", + "order": 42, + "placeholder": "placeholder", + "required": True, + } + ], + "description": "description", + "expiration_days": 42, + "initial_price": 6.9, + "internal_notes": "internal_notes", + "legacy_payment_method_controls": True, + "payment_method_configuration": { + "disabled": ["acss_debit"], + "enabled": ["acss_debit"], + "include_platform_defaults": True, + }, + "plan_type": "renewal", + "release_method": "buy_now", + "renewal_price": 6.9, + "stock": 42, + "trial_period_days": 42, + "unlimited_stock": True, + "visibility": "visible", + }, + ) + assert_matches_type(Invoice, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_update(self, client: Whop) -> None: + response = client.invoices.with_raw_response.update( + id="inv_xxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + invoice = response.parse() + assert_matches_type(Invoice, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_update(self, client: Whop) -> None: + with client.invoices.with_streaming_response.update( + id="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(Invoice, 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_update(self, client: Whop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.invoices.with_raw_response.update( + id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Whop) -> None: + with client.invoices.with_streaming_response.list( + company_id="biz_xxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + invoice = response.parse() + assert_matches_type(SyncCursorPage[InvoiceListItem], invoice, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_delete(self, client: Whop) -> None: + invoice = client.invoices.delete( + "inv_xxxxxxxxxxxxxx", + ) + assert_matches_type(InvoiceDeleteResponse, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_delete(self, client: Whop) -> None: + response = client.invoices.with_raw_response.delete( + "inv_xxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + invoice = response.parse() + assert_matches_type(InvoiceDeleteResponse, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: Whop) -> None: + with client.invoices.with_streaming_response.delete( + "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(InvoiceDeleteResponse, 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_delete(self, client: Whop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.invoices.with_raw_response.delete( + "", + ) + + @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: @@ -697,27 +739,12 @@ class TestAsyncInvoices: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_create_overload_1(self, async_client: AsyncWhop) -> None: - invoice = await async_client.invoices.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", - plan={}, - product={"title": "title"}, - ) - assert_matches_type(Invoice, invoice, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_create_with_all_params_overload_1(self, async_client: AsyncWhop) -> None: invoice = await async_client.invoices.create( collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", plan={ "billing_period": 42, "custom_fields": [ @@ -761,6 +788,8 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn }, charge_buyer_fee=True, customer_name="customer_name", + due_date=parse_datetime("2023-12-01T05:00:00.401Z"), + email_address="email_address", line_items=[ { "label": "label", @@ -769,63 +798,140 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn } ], mailing_address_id="ma_xxxxxxxxxxxxxxx", + member_id="mber_xxxxxxxxxxxxx", payment_method_id="pmt_xxxxxxxxxxxxxx", payment_token_id="payt_xxxxxxxxxxxxx", + save_as_draft=True, ) assert_matches_type(Invoice, invoice, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_create_overload_1(self, async_client: AsyncWhop) -> None: - response = await async_client.invoices.with_raw_response.create( + async def test_method_create_with_all_params_overload_2(self, async_client: AsyncWhop) -> None: + invoice = await async_client.invoices.create( collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", + plan={ + "billing_period": 42, + "custom_fields": [ + { + "field_type": "text", + "name": "name", + "id": "id", + "order": 42, + "placeholder": "placeholder", + "required": True, + } + ], + "description": "description", + "expiration_days": 42, + "initial_price": 6.9, + "internal_notes": "internal_notes", + "plan_type": "renewal", + "release_method": "buy_now", + "renewal_price": 6.9, + "stock": 42, + "trial_period_days": 42, + "unlimited_stock": True, + "visibility": "visible", + }, + 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", due_date=parse_datetime("2023-12-01T05:00:00.401Z"), + email_address="email_address", + line_items=[ + { + "label": "label", + "unit_price": 6.9, + "quantity": 6.9, + } + ], + mailing_address_id="ma_xxxxxxxxxxxxxxx", member_id="mber_xxxxxxxxxxxxx", - plan={}, - product={"title": "title"}, + payment_method_id="pmt_xxxxxxxxxxxxxx", + payment_token_id="payt_xxxxxxxxxxxxx", + save_as_draft=True, ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - invoice = await response.parse() assert_matches_type(Invoice, invoice, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_create_overload_1(self, async_client: AsyncWhop) -> None: - async with async_client.invoices.with_streaming_response.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", - plan={}, - product={"title": "title"}, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - invoice = await response.parse() - assert_matches_type(Invoice, invoice, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_create_overload_2(self, async_client: AsyncWhop) -> None: + async def test_method_create_with_all_params_overload_3(self, async_client: AsyncWhop) -> None: invoice = await async_client.invoices.create( collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", - plan={}, - product={"title": "title"}, + member_id="mber_xxxxxxxxxxxxx", + plan={ + "billing_period": 42, + "custom_fields": [ + { + "field_type": "text", + "name": "name", + "id": "id", + "order": 42, + "placeholder": "placeholder", + "required": True, + } + ], + "description": "description", + "expiration_days": 42, + "initial_price": 6.9, + "internal_notes": "internal_notes", + "plan_type": "renewal", + "release_method": "buy_now", + "renewal_price": 6.9, + "stock": 42, + "trial_period_days": 42, + "unlimited_stock": True, + "visibility": "visible", + }, + 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", ) assert_matches_type(Invoice, invoice, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_create_with_all_params_overload_2(self, async_client: AsyncWhop) -> None: + async def test_method_create_with_all_params_overload_4(self, async_client: AsyncWhop) -> None: invoice = await async_client.invoices.create( collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", @@ -855,10 +961,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn "unlimited_stock": True, "visibility": "visible", }, - product={ - "title": "title", - "product_tax_code_id": "ptc_xxxxxxxxxxxxxx", - }, + product_id="prod_xxxxxxxxxxxxx", automatically_finalizes_at=parse_datetime("2023-12-01T05:00:00.401Z"), billing_address={ "city": "city", @@ -889,12 +992,102 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_create_overload_2(self, async_client: AsyncWhop) -> None: + async def test_method_retrieve(self, async_client: AsyncWhop) -> None: + invoice = await async_client.invoices.retrieve( + "inv_xxxxxxxxxxxxxx", + ) + assert_matches_type(Invoice, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None: + response = await async_client.invoices.with_raw_response.retrieve( + "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(Invoice, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None: + async with async_client.invoices.with_streaming_response.retrieve( + "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(Invoice, 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_retrieve(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.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncWhop) -> None: + invoice = await async_client.invoices.list( + company_id="biz_xxxxxxxxxxxxxx", + ) + assert_matches_type(AsyncCursorPage[InvoiceListItem], invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None: + invoice = await async_client.invoices.list( + company_id="biz_xxxxxxxxxxxxxx", + after="after", + before="before", + collection_methods=["send_invoice"], + created_after=parse_datetime("2023-12-01T05:00:00.401Z"), + created_before=parse_datetime("2023-12-01T05:00:00.401Z"), + direction="asc", + first=42, + last=42, + order="id", + product_ids=["string"], + statuses=["draft"], + ) + assert_matches_type(AsyncCursorPage[InvoiceListItem], invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncWhop) -> None: + response = await async_client.invoices.with_raw_response.list( + company_id="biz_xxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + invoice = await response.parse() + assert_matches_type(AsyncCursorPage[InvoiceListItem], invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_overload_1(self, async_client: AsyncWhop) -> None: + invoice = await async_client.invoices.create( + collection_method="send_invoice", + company_id="biz_xxxxxxxxxxxxxx", + plan={}, + product={"title": "title"}, + ) + assert_matches_type(Invoice, invoice, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create_overload_1(self, async_client: AsyncWhop) -> None: response = await async_client.invoices.with_raw_response.create( collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", plan={}, product={"title": "title"}, ) @@ -906,12 +1099,10 @@ async def test_raw_response_create_overload_2(self, async_client: AsyncWhop) -> @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_create_overload_2(self, async_client: AsyncWhop) -> None: + async def test_streaming_response_create_overload_1(self, async_client: AsyncWhop) -> None: async with async_client.invoices.with_streaming_response.create( collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", plan={}, product={"title": "title"}, ) as response: @@ -925,12 +1116,10 @@ async def test_streaming_response_create_overload_2(self, async_client: AsyncWho @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_create_overload_3(self, async_client: AsyncWhop) -> None: + async def test_method_create_overload_2(self, async_client: AsyncWhop) -> None: invoice = await async_client.invoices.create( collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", plan={}, product_id="prod_xxxxxxxxxxxxx", ) @@ -938,73 +1127,10 @@ async def test_method_create_overload_3(self, async_client: AsyncWhop) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_create_with_all_params_overload_3(self, async_client: AsyncWhop) -> None: - invoice = await async_client.invoices.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", - plan={ - "billing_period": 42, - "custom_fields": [ - { - "field_type": "text", - "name": "name", - "id": "id", - "order": 42, - "placeholder": "placeholder", - "required": True, - } - ], - "description": "description", - "expiration_days": 42, - "initial_price": 6.9, - "internal_notes": "internal_notes", - "plan_type": "renewal", - "release_method": "buy_now", - "renewal_price": 6.9, - "stock": 42, - "trial_period_days": 42, - "unlimited_stock": True, - "visibility": "visible", - }, - 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", - ) - assert_matches_type(Invoice, invoice, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_create_overload_3(self, async_client: AsyncWhop) -> None: + async def test_raw_response_create_overload_2(self, async_client: AsyncWhop) -> None: response = await async_client.invoices.with_raw_response.create( collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", plan={}, product_id="prod_xxxxxxxxxxxxx", ) @@ -1016,12 +1142,10 @@ async def test_raw_response_create_overload_3(self, async_client: AsyncWhop) -> @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_create_overload_3(self, async_client: AsyncWhop) -> None: + async def test_streaming_response_create_overload_2(self, async_client: AsyncWhop) -> None: async with async_client.invoices.with_streaming_response.create( collection_method="send_invoice", company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - member_id="mber_xxxxxxxxxxxxx", plan={}, product_id="prod_xxxxxxxxxxxxx", ) as response: @@ -1035,25 +1159,45 @@ async def test_streaming_response_create_overload_3(self, async_client: AsyncWho @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_create_overload_4(self, async_client: AsyncWhop) -> None: - invoice = await async_client.invoices.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", - plan={}, - product_id="prod_xxxxxxxxxxxxx", + async def test_method_update(self, async_client: AsyncWhop) -> None: + invoice = await async_client.invoices.update( + id="inv_xxxxxxxxxxxxxx", ) assert_matches_type(Invoice, invoice, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_create_with_all_params_overload_4(self, async_client: AsyncWhop) -> None: - invoice = await async_client.invoices.create( + async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> None: + invoice = await async_client.invoices.update( + id="inv_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, collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", + customer_name="customer_name", due_date=parse_datetime("2023-12-01T05:00:00.401Z"), email_address="email_address", + line_items=[ + { + "label": "label", + "unit_price": 6.9, + "quantity": 6.9, + } + ], + mailing_address_id="ma_xxxxxxxxxxxxxxx", + member_id="mber_xxxxxxxxxxxxx", + payment_method_id="pmt_xxxxxxxxxxxxxx", plan={ "billing_period": 42, "custom_fields": [ @@ -1070,6 +1214,12 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn "expiration_days": 42, "initial_price": 6.9, "internal_notes": "internal_notes", + "legacy_payment_method_controls": True, + "payment_method_configuration": { + "disabled": ["acss_debit"], + "enabled": ["acss_debit"], + "include_platform_defaults": True, + }, "plan_type": "renewal", "release_method": "buy_now", "renewal_price": 6.9, @@ -1078,45 +1228,14 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn "unlimited_stock": True, "visibility": "visible", }, - 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", ) assert_matches_type(Invoice, invoice, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_create_overload_4(self, async_client: AsyncWhop) -> None: - response = await async_client.invoices.with_raw_response.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", - plan={}, - product_id="prod_xxxxxxxxxxxxx", + async def test_raw_response_update(self, async_client: AsyncWhop) -> None: + response = await async_client.invoices.with_raw_response.update( + id="inv_xxxxxxxxxxxxxx", ) assert response.is_closed is True @@ -1126,14 +1245,9 @@ async def test_raw_response_create_overload_4(self, async_client: AsyncWhop) -> @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_create_overload_4(self, async_client: AsyncWhop) -> None: - async with async_client.invoices.with_streaming_response.create( - collection_method="send_invoice", - company_id="biz_xxxxxxxxxxxxxx", - due_date=parse_datetime("2023-12-01T05:00:00.401Z"), - email_address="email_address", - plan={}, - product_id="prod_xxxxxxxxxxxxx", + async def test_streaming_response_update(self, async_client: AsyncWhop) -> None: + async with async_client.invoices.with_streaming_response.update( + id="inv_xxxxxxxxxxxxxx", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1145,99 +1259,68 @@ async def test_streaming_response_create_overload_4(self, async_client: AsyncWho @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_retrieve(self, async_client: AsyncWhop) -> None: - invoice = await async_client.invoices.retrieve( - "inv_xxxxxxxxxxxxxx", - ) - assert_matches_type(Invoice, invoice, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None: - response = await async_client.invoices.with_raw_response.retrieve( - "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(Invoice, invoice, path=["response"]) + async def test_path_params_update(self, async_client: AsyncWhop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.invoices.with_raw_response.update( + id="", + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None: - async with async_client.invoices.with_streaming_response.retrieve( - "inv_xxxxxxxxxxxxxx", + async def test_streaming_response_list(self, async_client: AsyncWhop) -> None: + async with async_client.invoices.with_streaming_response.list( + company_id="biz_xxxxxxxxxxxxxx", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" invoice = await response.parse() - assert_matches_type(Invoice, invoice, path=["response"]) + assert_matches_type(AsyncCursorPage[InvoiceListItem], 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_retrieve(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.retrieve( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list(self, async_client: AsyncWhop) -> None: - invoice = await async_client.invoices.list( - company_id="biz_xxxxxxxxxxxxxx", - ) - assert_matches_type(AsyncCursorPage[InvoiceListItem], invoice, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None: - invoice = await async_client.invoices.list( - company_id="biz_xxxxxxxxxxxxxx", - after="after", - before="before", - collection_methods=["send_invoice"], - created_after=parse_datetime("2023-12-01T05:00:00.401Z"), - created_before=parse_datetime("2023-12-01T05:00:00.401Z"), - direction="asc", - first=42, - last=42, - order="id", - product_ids=["string"], - statuses=["draft"], + async def test_method_delete(self, async_client: AsyncWhop) -> None: + invoice = await async_client.invoices.delete( + "inv_xxxxxxxxxxxxxx", ) - assert_matches_type(AsyncCursorPage[InvoiceListItem], invoice, path=["response"]) + assert_matches_type(InvoiceDeleteResponse, invoice, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_list(self, async_client: AsyncWhop) -> None: - response = await async_client.invoices.with_raw_response.list( - company_id="biz_xxxxxxxxxxxxxx", + async def test_raw_response_delete(self, async_client: AsyncWhop) -> None: + response = await async_client.invoices.with_raw_response.delete( + "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(AsyncCursorPage[InvoiceListItem], invoice, path=["response"]) + assert_matches_type(InvoiceDeleteResponse, invoice, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_list(self, async_client: AsyncWhop) -> None: - async with async_client.invoices.with_streaming_response.list( - company_id="biz_xxxxxxxxxxxxxx", + async def test_streaming_response_delete(self, async_client: AsyncWhop) -> None: + async with async_client.invoices.with_streaming_response.delete( + "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(AsyncCursorPage[InvoiceListItem], invoice, path=["response"]) + assert_matches_type(InvoiceDeleteResponse, 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_delete(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.delete( + "", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_mark_paid(self, async_client: AsyncWhop) -> None: diff --git a/tests/test_client.py b/tests/test_client.py index f122cac..5b385e1 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -413,6 +413,30 @@ def test_default_query_option(self) -> None: client.close() + def test_hardcoded_query_params_in_url(self, client: Whop) -> None: + request = client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/foo?beta=true", + params={"limit": "10", "page": "abc"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/files/a%2Fb?beta=true", + params={"limit": "10"}, + ) + ) + assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" + def test_request_extra_json(self, client: Whop) -> None: request = client._build_request( FinalRequestOptions( @@ -1283,6 +1307,30 @@ async def test_default_query_option(self) -> None: await client.close() + async def test_hardcoded_query_params_in_url(self, async_client: AsyncWhop) -> None: + request = async_client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true"} + + request = async_client._build_request( + FinalRequestOptions( + method="get", + url="/foo?beta=true", + params={"limit": "10", "page": "abc"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} + + request = async_client._build_request( + FinalRequestOptions( + method="get", + url="/files/a%2Fb?beta=true", + params={"limit": "10"}, + ) + ) + assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" + def test_request_extra_json(self, client: Whop) -> None: request = client._build_request( FinalRequestOptions(