Skip to content

Commit 62ec1b4

Browse files
feat(api): manual updates
1 parent 9e5a808 commit 62ec1b4

7 files changed

Lines changed: 288 additions & 2 deletions

File tree

.stats.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 14
1+
configured_endpoints: 15
22
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brand-dev%2Fbrand.dev-c45c9faa82a7f8b0b0221deab17a0f6cc6b096906e192aea9ef535e17667008f.yml
33
openapi_spec_hash: f3330c699ed3a55e48cdeecfce379e7b
4-
config_hash: 7f48d078645cb8331328bcd6f6ab3281
4+
config_hash: 6f10592c7d0c3bafefc1271472283217

api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Types:
55
```python
66
from brand.dev.types import (
77
BrandRetrieveResponse,
8+
BrandAIProductsResponse,
89
BrandAIQueryResponse,
910
BrandFontsResponse,
1011
BrandIdentifyFromTransactionResponse,
@@ -24,6 +25,7 @@ from brand.dev.types import (
2425
Methods:
2526

2627
- <code title="get /brand/retrieve">client.brand.<a href="./src/brand/dev/resources/brand.py">retrieve</a>(\*\*<a href="src/brand/dev/types/brand_retrieve_params.py">params</a>) -> <a href="./src/brand/dev/types/brand_retrieve_response.py">BrandRetrieveResponse</a></code>
28+
- <code title="post /brand/ai/products">client.brand.<a href="./src/brand/dev/resources/brand.py">ai_products</a>(\*\*<a href="src/brand/dev/types/brand_ai_products_params.py">params</a>) -> <a href="./src/brand/dev/types/brand_ai_products_response.py">BrandAIProductsResponse</a></code>
2729
- <code title="post /brand/ai/query">client.brand.<a href="./src/brand/dev/resources/brand.py">ai_query</a>(\*\*<a href="src/brand/dev/types/brand_ai_query_params.py">params</a>) -> <a href="./src/brand/dev/types/brand_ai_query_response.py">BrandAIQueryResponse</a></code>
2830
- <code title="get /brand/fonts">client.brand.<a href="./src/brand/dev/resources/brand.py">fonts</a>(\*\*<a href="src/brand/dev/types/brand_fonts_params.py">params</a>) -> <a href="./src/brand/dev/types/brand_fonts_response.py">BrandFontsResponse</a></code>
2931
- <code title="get /brand/transaction_identifier">client.brand.<a href="./src/brand/dev/resources/brand.py">identify_from_transaction</a>(\*\*<a href="src/brand/dev/types/brand_identify_from_transaction_params.py">params</a>) -> <a href="./src/brand/dev/types/brand_identify_from_transaction_response.py">BrandIdentifyFromTransactionResponse</a></code>

src/brand/dev/resources/brand.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
brand_retrieve_params,
1515
brand_screenshot_params,
1616
brand_styleguide_params,
17+
brand_ai_products_params,
1718
brand_retrieve_naics_params,
1819
brand_retrieve_by_isin_params,
1920
brand_retrieve_by_name_params,
@@ -40,6 +41,7 @@
4041
from ..types.brand_retrieve_response import BrandRetrieveResponse
4142
from ..types.brand_screenshot_response import BrandScreenshotResponse
4243
from ..types.brand_styleguide_response import BrandStyleguideResponse
44+
from ..types.brand_ai_products_response import BrandAIProductsResponse
4345
from ..types.brand_retrieve_naics_response import BrandRetrieveNaicsResponse
4446
from ..types.brand_retrieve_by_isin_response import BrandRetrieveByIsinResponse
4547
from ..types.brand_retrieve_by_name_response import BrandRetrieveByNameResponse
@@ -187,6 +189,58 @@ def retrieve(
187189
cast_to=BrandRetrieveResponse,
188190
)
189191

192+
def ai_products(
193+
self,
194+
*,
195+
domain: str,
196+
max_products: int | Omit = omit,
197+
timeout_ms: int | Omit = omit,
198+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
199+
# The extra values given here take precedence over values defined on the client or passed to this method.
200+
extra_headers: Headers | None = None,
201+
extra_query: Query | None = None,
202+
extra_body: Body | None = None,
203+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
204+
) -> BrandAIProductsResponse:
205+
"""Beta feature: Use AI to extract product information from a brand's website.
206+
207+
The
208+
AI will analyze the website and return a list of products with details such as
209+
name, description, pricing, features, and more.
210+
211+
Args:
212+
domain: The domain name to analyze
213+
214+
max_products: Maximum number of products to extract.
215+
216+
timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer
217+
than this value, it will be aborted with a 408 status code. Maximum allowed
218+
value is 300000ms (5 minutes).
219+
220+
extra_headers: Send extra headers
221+
222+
extra_query: Add additional query parameters to the request
223+
224+
extra_body: Add additional JSON properties to the request
225+
226+
timeout: Override the client-level default timeout for this request, in seconds
227+
"""
228+
return self._post(
229+
"/brand/ai/products",
230+
body=maybe_transform(
231+
{
232+
"domain": domain,
233+
"max_products": max_products,
234+
"timeout_ms": timeout_ms,
235+
},
236+
brand_ai_products_params.BrandAIProductsParams,
237+
),
238+
options=make_request_options(
239+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
240+
),
241+
cast_to=BrandAIProductsResponse,
242+
)
243+
190244
def ai_query(
191245
self,
192246
*,
@@ -1674,6 +1728,58 @@ async def retrieve(
16741728
cast_to=BrandRetrieveResponse,
16751729
)
16761730

1731+
async def ai_products(
1732+
self,
1733+
*,
1734+
domain: str,
1735+
max_products: int | Omit = omit,
1736+
timeout_ms: int | Omit = omit,
1737+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1738+
# The extra values given here take precedence over values defined on the client or passed to this method.
1739+
extra_headers: Headers | None = None,
1740+
extra_query: Query | None = None,
1741+
extra_body: Body | None = None,
1742+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
1743+
) -> BrandAIProductsResponse:
1744+
"""Beta feature: Use AI to extract product information from a brand's website.
1745+
1746+
The
1747+
AI will analyze the website and return a list of products with details such as
1748+
name, description, pricing, features, and more.
1749+
1750+
Args:
1751+
domain: The domain name to analyze
1752+
1753+
max_products: Maximum number of products to extract.
1754+
1755+
timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer
1756+
than this value, it will be aborted with a 408 status code. Maximum allowed
1757+
value is 300000ms (5 minutes).
1758+
1759+
extra_headers: Send extra headers
1760+
1761+
extra_query: Add additional query parameters to the request
1762+
1763+
extra_body: Add additional JSON properties to the request
1764+
1765+
timeout: Override the client-level default timeout for this request, in seconds
1766+
"""
1767+
return await self._post(
1768+
"/brand/ai/products",
1769+
body=await async_maybe_transform(
1770+
{
1771+
"domain": domain,
1772+
"max_products": max_products,
1773+
"timeout_ms": timeout_ms,
1774+
},
1775+
brand_ai_products_params.BrandAIProductsParams,
1776+
),
1777+
options=make_request_options(
1778+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
1779+
),
1780+
cast_to=BrandAIProductsResponse,
1781+
)
1782+
16771783
async def ai_query(
16781784
self,
16791785
*,
@@ -3033,6 +3139,9 @@ def __init__(self, brand: BrandResource) -> None:
30333139
self.retrieve = to_raw_response_wrapper(
30343140
brand.retrieve,
30353141
)
3142+
self.ai_products = to_raw_response_wrapper(
3143+
brand.ai_products,
3144+
)
30363145
self.ai_query = to_raw_response_wrapper(
30373146
brand.ai_query,
30383147
)
@@ -3081,6 +3190,9 @@ def __init__(self, brand: AsyncBrandResource) -> None:
30813190
self.retrieve = async_to_raw_response_wrapper(
30823191
brand.retrieve,
30833192
)
3193+
self.ai_products = async_to_raw_response_wrapper(
3194+
brand.ai_products,
3195+
)
30843196
self.ai_query = async_to_raw_response_wrapper(
30853197
brand.ai_query,
30863198
)
@@ -3129,6 +3241,9 @@ def __init__(self, brand: BrandResource) -> None:
31293241
self.retrieve = to_streamed_response_wrapper(
31303242
brand.retrieve,
31313243
)
3244+
self.ai_products = to_streamed_response_wrapper(
3245+
brand.ai_products,
3246+
)
31323247
self.ai_query = to_streamed_response_wrapper(
31333248
brand.ai_query,
31343249
)
@@ -3177,6 +3292,9 @@ def __init__(self, brand: AsyncBrandResource) -> None:
31773292
self.retrieve = async_to_streamed_response_wrapper(
31783293
brand.retrieve,
31793294
)
3295+
self.ai_products = async_to_streamed_response_wrapper(
3296+
brand.ai_products,
3297+
)
31803298
self.ai_query = async_to_streamed_response_wrapper(
31813299
brand.ai_query,
31823300
)

src/brand/dev/types/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
from .brand_retrieve_response import BrandRetrieveResponse as BrandRetrieveResponse
1313
from .brand_screenshot_params import BrandScreenshotParams as BrandScreenshotParams
1414
from .brand_styleguide_params import BrandStyleguideParams as BrandStyleguideParams
15+
from .brand_ai_products_params import BrandAIProductsParams as BrandAIProductsParams
1516
from .brand_screenshot_response import BrandScreenshotResponse as BrandScreenshotResponse
1617
from .brand_styleguide_response import BrandStyleguideResponse as BrandStyleguideResponse
18+
from .brand_ai_products_response import BrandAIProductsResponse as BrandAIProductsResponse
1719
from .brand_retrieve_naics_params import BrandRetrieveNaicsParams as BrandRetrieveNaicsParams
1820
from .brand_retrieve_by_isin_params import BrandRetrieveByIsinParams as BrandRetrieveByIsinParams
1921
from .brand_retrieve_by_name_params import BrandRetrieveByNameParams as BrandRetrieveByNameParams
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from __future__ import annotations
4+
5+
from typing_extensions import Required, Annotated, TypedDict
6+
7+
from .._utils import PropertyInfo
8+
9+
__all__ = ["BrandAIProductsParams"]
10+
11+
12+
class BrandAIProductsParams(TypedDict, total=False):
13+
domain: Required[str]
14+
"""The domain name to analyze"""
15+
16+
max_products: Annotated[int, PropertyInfo(alias="maxProducts")]
17+
"""Maximum number of products to extract."""
18+
19+
timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")]
20+
"""Optional timeout in milliseconds for the request.
21+
22+
If the request takes longer than this value, it will be aborted with a 408
23+
status code. Maximum allowed value is 300000ms (5 minutes).
24+
"""
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from typing import List, Optional
4+
from typing_extensions import Literal
5+
6+
from .._models import BaseModel
7+
8+
__all__ = ["BrandAIProductsResponse", "Product"]
9+
10+
11+
class Product(BaseModel):
12+
description: str
13+
"""Description of the product"""
14+
15+
features: List[str]
16+
"""List of product features"""
17+
18+
name: str
19+
"""Name of the product"""
20+
21+
tags: List[str]
22+
"""Tags associated with the product"""
23+
24+
target_audience: List[str]
25+
"""Target audience for the product (array of strings)"""
26+
27+
billing_frequency: Optional[Literal["monthly", "yearly", "one_time", "usage_based"]] = None
28+
"""Billing frequency for the product"""
29+
30+
category: Optional[str] = None
31+
"""Category of the product"""
32+
33+
currency: Optional[str] = None
34+
"""Currency code for the price (e.g., USD, EUR)"""
35+
36+
image_url: Optional[str] = None
37+
"""URL to the product image"""
38+
39+
price: Optional[float] = None
40+
"""Price of the product"""
41+
42+
pricing_model: Optional[Literal["per_seat", "flat", "tiered", "freemium", "custom"]] = None
43+
"""Pricing model for the product"""
44+
45+
url: Optional[str] = None
46+
"""URL to the product page"""
47+
48+
49+
class BrandAIProductsResponse(BaseModel):
50+
products: Optional[List[Product]] = None
51+
"""Array of products extracted from the website"""

tests/api_resources/test_brand.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
BrandAIQueryResponse,
1515
BrandPrefetchResponse,
1616
BrandRetrieveResponse,
17+
BrandAIProductsResponse,
1718
BrandScreenshotResponse,
1819
BrandStyleguideResponse,
1920
BrandRetrieveNaicsResponse,
@@ -71,6 +72,50 @@ def test_streaming_response_retrieve(self, client: BrandDev) -> None:
7172

7273
assert cast(Any, response.is_closed) is True
7374

75+
@pytest.mark.skip(reason="Prism tests are disabled")
76+
@parametrize
77+
def test_method_ai_products(self, client: BrandDev) -> None:
78+
brand = client.brand.ai_products(
79+
domain="domain",
80+
)
81+
assert_matches_type(BrandAIProductsResponse, brand, path=["response"])
82+
83+
@pytest.mark.skip(reason="Prism tests are disabled")
84+
@parametrize
85+
def test_method_ai_products_with_all_params(self, client: BrandDev) -> None:
86+
brand = client.brand.ai_products(
87+
domain="domain",
88+
max_products=1,
89+
timeout_ms=1,
90+
)
91+
assert_matches_type(BrandAIProductsResponse, brand, path=["response"])
92+
93+
@pytest.mark.skip(reason="Prism tests are disabled")
94+
@parametrize
95+
def test_raw_response_ai_products(self, client: BrandDev) -> None:
96+
response = client.brand.with_raw_response.ai_products(
97+
domain="domain",
98+
)
99+
100+
assert response.is_closed is True
101+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
102+
brand = response.parse()
103+
assert_matches_type(BrandAIProductsResponse, brand, path=["response"])
104+
105+
@pytest.mark.skip(reason="Prism tests are disabled")
106+
@parametrize
107+
def test_streaming_response_ai_products(self, client: BrandDev) -> None:
108+
with client.brand.with_streaming_response.ai_products(
109+
domain="domain",
110+
) as response:
111+
assert not response.is_closed
112+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
113+
114+
brand = response.parse()
115+
assert_matches_type(BrandAIProductsResponse, brand, path=["response"])
116+
117+
assert cast(Any, response.is_closed) is True
118+
74119
@pytest.mark.skip(reason="Prism tests are disabled")
75120
@parametrize
76121
def test_method_ai_query(self, client: BrandDev) -> None:
@@ -743,6 +788,50 @@ async def test_streaming_response_retrieve(self, async_client: AsyncBrandDev) ->
743788

744789
assert cast(Any, response.is_closed) is True
745790

791+
@pytest.mark.skip(reason="Prism tests are disabled")
792+
@parametrize
793+
async def test_method_ai_products(self, async_client: AsyncBrandDev) -> None:
794+
brand = await async_client.brand.ai_products(
795+
domain="domain",
796+
)
797+
assert_matches_type(BrandAIProductsResponse, brand, path=["response"])
798+
799+
@pytest.mark.skip(reason="Prism tests are disabled")
800+
@parametrize
801+
async def test_method_ai_products_with_all_params(self, async_client: AsyncBrandDev) -> None:
802+
brand = await async_client.brand.ai_products(
803+
domain="domain",
804+
max_products=1,
805+
timeout_ms=1,
806+
)
807+
assert_matches_type(BrandAIProductsResponse, brand, path=["response"])
808+
809+
@pytest.mark.skip(reason="Prism tests are disabled")
810+
@parametrize
811+
async def test_raw_response_ai_products(self, async_client: AsyncBrandDev) -> None:
812+
response = await async_client.brand.with_raw_response.ai_products(
813+
domain="domain",
814+
)
815+
816+
assert response.is_closed is True
817+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
818+
brand = await response.parse()
819+
assert_matches_type(BrandAIProductsResponse, brand, path=["response"])
820+
821+
@pytest.mark.skip(reason="Prism tests are disabled")
822+
@parametrize
823+
async def test_streaming_response_ai_products(self, async_client: AsyncBrandDev) -> None:
824+
async with async_client.brand.with_streaming_response.ai_products(
825+
domain="domain",
826+
) as response:
827+
assert not response.is_closed
828+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
829+
830+
brand = await response.parse()
831+
assert_matches_type(BrandAIProductsResponse, brand, path=["response"])
832+
833+
assert cast(Any, response.is_closed) is True
834+
746835
@pytest.mark.skip(reason="Prism tests are disabled")
747836
@parametrize
748837
async def test_method_ai_query(self, async_client: AsyncBrandDev) -> None:

0 commit comments

Comments
 (0)