From b85a3787bb1871cb46cbdde7bb809f590cb143ef Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 7 Apr 2026 08:13:25 +0000
Subject: [PATCH 01/10] feat(api): api update
---
.stats.yml | 4 +-
tests/api_resources/test_invoices.py | 592 +++++++++------------------
2 files changed, 188 insertions(+), 408 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 32314d6..d6e41dd 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
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-40ac9ec5dc42b71cbb70e06f0a71735e54dd4af6eb3f3bd0496438ca70104405.yml
+openapi_spec_hash: bf701a31274e99b62290cf6b02d203bd
config_hash: fee5c8b2e5f00cef705ad48c3f3b5b5a
diff --git a/tests/api_resources/test_invoices.py b/tests/api_resources/test_invoices.py
index 97377e3..17e9551 100644
--- a/tests/api_resources/test_invoices.py
+++ b/tests/api_resources/test_invoices.py
@@ -24,19 +24,6 @@
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:
@@ -101,55 +88,6 @@ def test_method_create_with_all_params_overload_1(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_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"},
- )
- 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_2(self, client: Whop) -> None:
@@ -214,55 +152,6 @@ def test_method_create_with_all_params_overload_2(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_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",
- )
- 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_3(self, client: Whop) -> None:
@@ -324,55 +213,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 +274,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,43 +357,129 @@ 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",
+ plan={},
+ product={"title": "title"},
+ )
+ 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",
+ 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",
+ 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(SyncCursorPage[InvoiceListItem], 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_method_mark_paid(self, client: Whop) -> None:
- invoice = client.invoices.mark_paid(
- "inv_xxxxxxxxxxxxxx",
+ 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(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_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(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_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_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_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"
@@ -697,19 +587,6 @@ 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:
@@ -774,55 +651,6 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn
)
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"),
- 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 = 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:
- 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"},
- )
- 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:
@@ -887,55 +715,6 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn
)
assert_matches_type(Invoice, invoice, path=["response"])
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_create_overload_2(self, async_client: AsyncWhop) -> None:
- response = await async_client.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 = 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_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"),
- 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 = 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_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={},
- product_id="prod_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_3(self, async_client: AsyncWhop) -> None:
@@ -997,55 +776,6 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn
)
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:
- 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",
- )
-
- 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_3(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:
- 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_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",
- )
- 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:
@@ -1107,42 +837,6 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn
)
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",
- )
-
- 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_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",
- ) 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_retrieve(self, async_client: AsyncWhop) -> None:
@@ -1224,6 +918,92 @@ async def test_raw_response_list(self, async_client: AsyncWhop) -> None:
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",
+ plan={},
+ product={"title": "title"},
+ )
+
+ 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",
+ 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:
+ invoice = await async_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
+ 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",
+ plan={},
+ product_id="prod_xxxxxxxxxxxxx",
+ )
+
+ 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_2(self, async_client: AsyncWhop) -> None:
+ async with async_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 = 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_streaming_response_list(self, async_client: AsyncWhop) -> None:
From d17a56ff7a5e89ce7863e3d44bd06912fc3ce94c Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 10 Apr 2026 02:32:18 +0000
Subject: [PATCH 02/10] feat(api): api update
---
src/whop_sdk/resources/invoices.py | 524 +++--------------
src/whop_sdk/types/invoice_create_params.py | 619 +++++---------------
tests/api_resources/test_invoices.py | 34 +-
3 files changed, 246 insertions(+), 931 deletions(-)
diff --git a/src/whop_sdk/resources/invoices.py b/src/whop_sdk/resources/invoices.py
index b3ef3f2..b36da40 100644
--- a/src/whop_sdk/resources/invoices.py
+++ b/src/whop_sdk/resources/invoices.py
@@ -59,20 +59,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 +96,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 +114,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 +154,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 +191,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 +208,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 +243,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 +282,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,
@@ -746,20 +578,20 @@ async 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,
@@ -783,11 +615,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.
-
- 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.
@@ -806,106 +633,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.
- 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
- async 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
@@ -922,20 +673,20 @@ async 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,
@@ -959,11 +710,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.
-
- 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.
@@ -981,105 +727,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.
- 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
- async 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
@@ -1091,39 +762,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 +801,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,
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/tests/api_resources/test_invoices.py b/tests/api_resources/test_invoices.py
index 17e9551..2ea12b2 100644
--- a/tests/api_resources/test_invoices.py
+++ b/tests/api_resources/test_invoices.py
@@ -30,8 +30,6 @@ 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": [
@@ -75,6 +73,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",
@@ -83,8 +83,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",
+ save_as_draft=True,
)
assert_matches_type(Invoice, invoice, path=["response"])
@@ -94,8 +96,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": [
@@ -120,10 +120,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",
@@ -139,6 +136,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",
@@ -147,8 +146,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",
+ save_as_draft=True,
)
assert_matches_type(Invoice, invoice, path=["response"])
@@ -593,8 +594,6 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn
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": [
@@ -638,6 +637,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",
@@ -646,8 +647,10 @@ 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"])
@@ -657,8 +660,6 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn
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={
"billing_period": 42,
"custom_fields": [
@@ -683,10 +684,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",
@@ -702,6 +700,8 @@ async def test_method_create_with_all_params_overload_2(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",
@@ -710,8 +710,10 @@ async def test_method_create_with_all_params_overload_2(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"])
From 2a7a622f89f262b1b2b6df0fb6354947db0e20f9 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 7 Apr 2026 16:09:44 +0000
Subject: [PATCH 03/10] fix(client): preserve hardcoded query params when
merging with user params
---
src/whop_sdk/_base_client.py | 4 +++
tests/test_client.py | 48 ++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+)
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/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(
From 1e398a68ff927c66eefaef4eae88fb2aecef9581 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 8 Apr 2026 19:13:44 +0000
Subject: [PATCH 04/10] feat(api): api update
---
.stats.yml | 4 ++--
src/whop_sdk/types/membership_list_response.py | 2 +-
src/whop_sdk/types/shared/membership.py | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index d6e41dd..e601eba 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-40ac9ec5dc42b71cbb70e06f0a71735e54dd4af6eb3f3bd0496438ca70104405.yml
-openapi_spec_hash: bf701a31274e99b62290cf6b02d203bd
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-e284f164f530a4ebe56001acedd17b184c1886a923699ab4084c7a41ebb73d5a.yml
+openapi_spec_hash: 20f5bb8d4625bd9695845a77279926ea
config_hash: fee5c8b2e5f00cef705ad48c3f3b5b5a
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/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.
From 0216e92f1a2b537dd36a428dbf46fdc1dfe23cba Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 8 Apr 2026 21:13:29 +0000
Subject: [PATCH 05/10] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index e601eba..3efdf4a 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-e284f164f530a4ebe56001acedd17b184c1886a923699ab4084c7a41ebb73d5a.yml
-openapi_spec_hash: 20f5bb8d4625bd9695845a77279926ea
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-2132c11b688fd9f9a5237d808f19e9acb2dafe2f3c6e159e93b65465718ae4be.yml
+openapi_spec_hash: 53bc06afa2f9f32cc863f8300038b001
config_hash: fee5c8b2e5f00cef705ad48c3f3b5b5a
From 11e1148f16a6050fb21bac04588e9fde2c1106a3 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 9 Apr 2026 04:13:46 +0000
Subject: [PATCH 06/10] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 3efdf4a..66cac6a 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-2132c11b688fd9f9a5237d808f19e9acb2dafe2f3c6e159e93b65465718ae4be.yml
-openapi_spec_hash: 53bc06afa2f9f32cc863f8300038b001
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-705412f3f0007209701ba39dbdf18a040585fc44d17faa7bf90885e9688cb4a7.yml
+openapi_spec_hash: 2d7cf217dfb8f6d9a272c0643b30d013
config_hash: fee5c8b2e5f00cef705ad48c3f3b5b5a
From d2693a0106620b442ef9e981cd8f8cc44ef26e8f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 9 Apr 2026 06:13:34 +0000
Subject: [PATCH 07/10] feat(api): api update
---
.stats.yml | 4 ++--
src/whop_sdk/types/payment_method_types.py | 6 ++++++
src/whop_sdk/types/payment_provider.py | 1 +
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 66cac6a..c9f22c5 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-705412f3f0007209701ba39dbdf18a040585fc44d17faa7bf90885e9688cb4a7.yml
-openapi_spec_hash: 2d7cf217dfb8f6d9a272c0643b30d013
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-d0bafad1dd96b7430affd043c4f997985ab34c6c6b42a9839e0e9edc4f9c59b1.yml
+openapi_spec_hash: 0867d34f6d45f6d9e3b95139ef7139bd
config_hash: fee5c8b2e5f00cef705ad48c3f3b5b5a
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",
]
From e2d2d02942362ca8c490a7435495a9ca51b6ac2c Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 9 Apr 2026 09:13:44 +0000
Subject: [PATCH 08/10] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index c9f22c5..9c7e46d 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-d0bafad1dd96b7430affd043c4f997985ab34c6c6b42a9839e0e9edc4f9c59b1.yml
-openapi_spec_hash: 0867d34f6d45f6d9e3b95139ef7139bd
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-58749e1928f402cc3e236d38b53bce3b10530bfaccbe426181bba9b1bfc42498.yml
+openapi_spec_hash: ecea6e6c4b93665aee5554839a26ded8
config_hash: fee5c8b2e5f00cef705ad48c3f3b5b5a
From c40100933895bfe8f2f20d480e8348b7092b4c89 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 10 Apr 2026 01:55:20 +0000
Subject: [PATCH 09/10] feat(api): manual updates
---
.stats.yml | 4 +-
api.md | 5 +-
src/whop_sdk/resources/invoices.py | 281 +++++++++++++++-
src/whop_sdk/types/__init__.py | 4 +
.../checkout_configuration_create_params.py | 14 +-
src/whop_sdk/types/checkout_font.py | 7 +
src/whop_sdk/types/checkout_shape.py | 7 +
src/whop_sdk/types/invoice_delete_response.py | 7 +
src/whop_sdk/types/invoice_update_params.py | 229 +++++++++++++
src/whop_sdk/types/plan_create_params.py | 6 +-
src/whop_sdk/types/plan_update_params.py | 6 +-
tests/api_resources/test_invoices.py | 301 ++++++++++++++++++
12 files changed, 857 insertions(+), 14 deletions(-)
create mode 100644 src/whop_sdk/types/checkout_font.py
create mode 100644 src/whop_sdk/types/checkout_shape.py
create mode 100644 src/whop_sdk/types/invoice_delete_response.py
create mode 100644 src/whop_sdk/types/invoice_update_params.py
diff --git a/.stats.yml b/.stats.yml
index 9c7e46d..fc1b600 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 193
+configured_endpoints: 195
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-58749e1928f402cc3e236d38b53bce3b10530bfaccbe426181bba9b1bfc42498.yml
openapi_spec_hash: ecea6e6c4b93665aee5554839a26ded8
-config_hash: fee5c8b2e5f00cef705ad48c3f3b5b5a
+config_hash: 2ceaf6cd488db626c181a1ca9460ace6
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/src/whop_sdk/resources/invoices.py b/src/whop_sdk/resources/invoices.py
index b36da40..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
@@ -344,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,
*,
@@ -438,6 +529,43 @@ def list(
model=InvoiceListItem,
)
+ 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 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,
+ )
+
def mark_paid(
self,
id: str,
@@ -863,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,
*,
@@ -957,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,
@@ -1081,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,
)
@@ -1105,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,
)
@@ -1129,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,
)
@@ -1153,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_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/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/tests/api_resources/test_invoices.py b/tests/api_resources/test_invoices.py
index 2ea12b2..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,
)
@@ -442,6 +443,114 @@ def test_streaming_response_create_overload_2(self, client: Whop) -> None:
assert cast(Any, response.is_closed) is True
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_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:
@@ -456,6 +565,48 @@ def test_streaming_response_list(self, client: Whop) -> None:
assert cast(Any, response.is_closed) is True
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_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:
@@ -1006,6 +1157,114 @@ async def test_streaming_response_create_overload_2(self, async_client: AsyncWho
assert cast(Any, response.is_closed) is True
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ 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_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",
+ 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
+ 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
+ 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_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"
+
+ 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_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_list(self, async_client: AsyncWhop) -> None:
@@ -1020,6 +1279,48 @@ async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
assert cast(Any, response.is_closed) is True
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncWhop) -> None:
+ invoice = await async_client.invoices.delete(
+ "inv_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(InvoiceDeleteResponse, invoice, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_delete(self, async_client: AsyncWhop) -> None:
+ response = await async_client.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(InvoiceDeleteResponse, invoice, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_delete(self, async_client: AsyncWhop) -> None:
+ async with async_client.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(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:
From 3627daade03cfcf9102cbe39275d5a42915a91e1 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 10 Apr 2026 02:34:58 +0000
Subject: [PATCH 10/10] release: 0.0.37
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 17 +++++++++++++++++
pyproject.toml | 2 +-
src/whop_sdk/_version.py | 2 +-
4 files changed, 20 insertions(+), 3 deletions(-)
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/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/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/_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