diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5115900e..8553e6b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,10 +18,10 @@ jobs: lint: timeout-minutes: 10 name: lint - runs-on: ${{ github.repository == 'stainless-sdks/brand.dev-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | @@ -44,9 +44,9 @@ jobs: permissions: contents: read id-token: write - runs-on: ${{ github.repository == 'stainless-sdks/brand.dev-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | @@ -67,7 +67,7 @@ jobs: github.repository == 'stainless-sdks/brand.dev-python' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -84,10 +84,10 @@ jobs: test: timeout-minutes: 10 name: test - runs-on: ${{ github.repository == 'stainless-sdks/brand.dev-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 535e7fd5..d2f2691c 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 7778fb4a..d21c7a41 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'context-dot-dev/deprecated-brand-python-sdk' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b5fcdb93..ba2c5854 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.43.0" + ".": "1.44.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index bee881e8..3a0674f4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 20 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brand-dev%2Fbrand.dev-05a30711e18b0023520a660352d75595a050d1299bf0e3ee4a8cf55ded36aea2.yml -openapi_spec_hash: 8d0e1115a7d864f27c55cec3255d1e77 -config_hash: 91cf2dcefb99c39eb9cd3e98e15d6011 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brand-dev/brand.dev-7125e6c86991b26c287b8c298c82ca7962a32f9f6af4294855a0e53108b8963d.yml +openapi_spec_hash: 3f1221f259df9315d854d790ea710e57 +config_hash: cc61476116eb93980a98694cef45386a diff --git a/CHANGELOG.md b/CHANGELOG.md index d135655d..2d5264df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,86 @@ # Changelog +## 1.44.0 (2026-08-05) + +Full Changelog: [v1.43.0...v1.44.0](https://github.com/context-dot-dev/deprecated-brand-python-sdk/compare/v1.43.0...v1.44.0) + +### Features + +* **api:** api update ([51bf948](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/51bf94817c9bb7f07a7ba87d710334371f6a658f)) +* **api:** api update ([703ef35](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/703ef3597b8ade1129d7e3d9191134ccc47adfb4)) +* **api:** api update ([51745b2](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/51745b252b74eedfd5100c0e0f64a4f1e41ae320)) +* **api:** api update ([1f032b7](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/1f032b7f9e6a4a89cb6628b23153e59a7691261f)) +* **api:** api update ([5ca34aa](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/5ca34aa8034971169e2bfbf5367f30e3cb68f50d)) +* **api:** api update ([60f9a71](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/60f9a71a0b547d73ff171d00ed45301ed72cd84b)) +* **api:** api update ([b059e59](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/b059e5925b3733f5fffc00ce7da8afdfebe51e14)) +* **api:** api update ([445014e](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/445014e0f5d2bdbe0221ecc8999e9ebb70ce34d5)) +* **api:** api update ([b41ed13](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/b41ed132270724ef2d8aa7ed74cc3d754987334d)) +* **api:** api update ([1fa614f](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/1fa614fe452de9347bcc7ad4994949ef73464e0f)) +* **api:** api update ([f0eb6d6](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/f0eb6d6617d371caed07f21a6b10f6a6e9478eed)) +* **api:** api update ([a321b40](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/a321b406072a56c32794cf10b79548dafc29508a)) +* **api:** api update ([f96d2bf](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/f96d2bfe085f9724934a5b6a0841064172f3fbc7)) +* **api:** api update ([92be332](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/92be33255808a72338489c963bc16523e7dce74c)) +* **api:** api update ([cd67f5c](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/cd67f5c3a3559c2dbbac7d937c33827137d0579c)) +* **api:** api update ([f3a02b7](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/f3a02b778d05e9613943a29cba865017944e0355)) +* **api:** api update ([aceb4cf](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/aceb4cfb8e848877bac17b9a32fe8a626f22347e)) +* **api:** api update ([79a00c4](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/79a00c4b749b418c45d99bc3feb431cd9b1d7e02)) +* **api:** api update ([bd579fd](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/bd579fd5ab8c8f9c5224eb680e17c8498871b228)) +* **api:** api update ([4faf983](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/4faf983d75e7b72691ccfc9f4639d78de9b908fd)) +* **api:** api update ([234d568](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/234d56806ca02b209f848907dbae998d20066920)) +* **api:** api update ([835e3dc](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/835e3dc7d16ab4d4d7d8e6223b7671103ea99316)) +* **api:** api update ([b35bfa8](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/b35bfa83453d3ee820e8aab7a3914545924f6df8)) +* **api:** api update ([b868536](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/b86853684cdddc71c11371f7ac065004bd415078)) +* **api:** api update ([4f2fb89](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/4f2fb892f17828300c268e9e316477b3ee9de0b4)) +* **api:** api update ([bb7be8c](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/bb7be8c9f17e5a86aa69e7651cac1ae7b3c170c2)) +* **api:** api update ([90b98b6](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/90b98b60f940e7aa127cb2b52fbdf0e467cd45c1)) +* **api:** api update ([44865c2](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/44865c2f5a63e7d0e2e4ccd0c4d2c06206044fe8)) +* **api:** api update ([291415a](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/291415a60a6ee87cc6b27364e6b71e039ccb3590)) +* **api:** api update ([ce906ee](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/ce906ee12160bff29e64d8c140decf63c02fa104)) +* **api:** api update ([00262df](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/00262dff8700b717cdacde8d05c040c2e240b94b)) +* **api:** api update ([fcd2959](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/fcd2959f013e42957386b17c540c3b69fde4b08e)) +* **api:** api update ([34da1c0](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/34da1c09d1e5883a6134fba8bef1a2622a841a3d)) +* **api:** api update ([5573ee7](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/5573ee7e42f5018a95e85e66460bfccc3d695a2a)) +* **api:** api update ([e4f1307](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/e4f1307a639a0c14467bd4c6af34eafe96b86033)) +* **api:** api update ([3e783d9](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/3e783d9ad471999f34ed2cbc92a58099f15ce9cb)) +* **api:** api update ([f9047c7](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/f9047c77841d0b1707cdeab18880d93dd2e6a115)) +* **api:** api update ([390e85c](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/390e85cad5c6199e1a3d03de72e77d54f0108234)) +* **api:** api update ([74f22a5](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/74f22a55a3d82b5adcc63d5f12218a162180ae95)) +* **api:** api update ([a04e938](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/a04e9389794725781408dc53d635226406d89cb2)) +* **api:** api update ([b4672ab](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/b4672ab67f11664113177977497c75e6c5ce82f8)) +* **api:** api update ([b494e66](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/b494e66bdee0f1c447ee587836aa74c7955da0aa)) +* **api:** api update ([af4c2fa](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/af4c2fa317c4a5cd2ef86e6562fe41ff7436daed)) +* **api:** api update ([9d4a64e](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/9d4a64e28b1321eda8463d8c86ec8a130c78c318)) +* **api:** api update ([f13cc2b](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/f13cc2be3ce7c3355168ba62bb3bd5ec5aaf4105)) +* **api:** api update ([93a9472](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/93a9472c495a1d34afa82ff7a6889e32ff706e3f)) +* **api:** api update ([bf48ceb](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/bf48ceb8693e734ab3da2b89e80f394d351215e6)) +* **api:** api update ([b5e8905](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/b5e8905b3e8554890bda8c7eb9e4255c363f1a81)) +* **api:** api update ([04fafa1](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/04fafa1b94a4047cc9fb3825ab84e6f517baefc4)) +* **api:** api update ([bd0f93f](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/bd0f93f4df85dc1e822ca6b59fb7ce594976ad49)) +* **api:** api update ([a388d39](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/a388d39c93b50ec075a553957081a45f64b73d39)) +* **api:** api update ([9213463](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/9213463afaf5d76d3b706a5aef49082c72409189)) +* **api:** manual updates ([64bc711](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/64bc7110618dc0733bff60be38ccadaace6b62fb)) +* **internal/types:** support eagerly validating pydantic iterators ([06b88f4](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/06b88f47143a8e1c9182ceab6bf3c1f2eca6cfdc)) +* support setting headers via env ([0ce56bb](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/0ce56bbd77bbb7170a90b838c9dff09616dea488)) + + +### Bug Fixes + +* **client:** add missing f-string prefix in file type error message ([af1c0ca](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/af1c0cab6151a11859136bd4cbbd8a0a200acdd5)) +* **client:** preserve hardcoded query params when merging with user params ([a92d7b7](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/a92d7b7c66f52b259cbf31d938c8a70565190b5c)) +* ensure file data are only sent as 1 parameter ([9b72a51](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/9b72a51afe0d9992f3c52ee727c1ffc1ec76312f)) +* use correct field name format for multipart file arrays ([c74c369](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/c74c3699de55fd58f298fa9a9d378db7f677a344)) + + +### Performance Improvements + +* **client:** optimize file structure copying in multipart requests ([d7e4a18](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/d7e4a181dd0e9146f98bb51bb977300eac439c6e)) + + +### Chores + +* **internal:** more robust bootstrap script ([28007d9](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/28007d91dbe45b20fc33670466006d9934ac7c5a)) +* **internal:** reformat pyproject.toml ([3e37dca](https://github.com/context-dot-dev/deprecated-brand-python-sdk/commit/3e37dcaafaafaa677893794e66cec86afedb65ca)) + ## 1.43.0 (2026-04-03) Full Changelog: [v1.42.0...v1.43.0](https://github.com/context-dot-dev/deprecated-brand-python-sdk/compare/v1.42.0...v1.43.0) diff --git a/api.md b/api.md index 8b5d705f..39a39e2c 100644 --- a/api.md +++ b/api.md @@ -33,7 +33,7 @@ Methods: - client.brand.ai_product(\*\*params) -> BrandAIProductResponse - client.brand.ai_products(\*\*params) -> BrandAIProductsResponse - client.brand.ai_query(\*\*params) -> BrandAIQueryResponse -- client.brand.fonts(\*\*params) -> BrandFontsResponse +- client.brand.fonts(\*\*params) -> BrandFontsResponse - client.brand.identify_from_transaction(\*\*params) -> BrandIdentifyFromTransactionResponse - client.brand.prefetch(\*\*params) -> BrandPrefetchResponse - client.brand.prefetch_by_email(\*\*params) -> BrandPrefetchByEmailResponse @@ -41,11 +41,27 @@ Methods: - client.brand.retrieve_by_isin(\*\*params) -> BrandRetrieveByIsinResponse - client.brand.retrieve_by_name(\*\*params) -> BrandRetrieveByNameResponse - client.brand.retrieve_by_ticker(\*\*params) -> BrandRetrieveByTickerResponse -- client.brand.retrieve_naics(\*\*params) -> BrandRetrieveNaicsResponse +- client.brand.retrieve_naics(\*\*params) -> BrandRetrieveNaicsResponse - client.brand.retrieve_simplified(\*\*params) -> BrandRetrieveSimplifiedResponse -- client.brand.screenshot(\*\*params) -> BrandScreenshotResponse -- client.brand.styleguide(\*\*params) -> BrandStyleguideResponse +- client.brand.screenshot(\*\*params) -> BrandScreenshotResponse +- client.brand.styleguide(\*\*params) -> BrandStyleguideResponse - client.brand.web_scrape_html(\*\*params) -> BrandWebScrapeHTMLResponse - client.brand.web_scrape_images(\*\*params) -> BrandWebScrapeImagesResponse - client.brand.web_scrape_md(\*\*params) -> BrandWebScrapeMdResponse - client.brand.web_scrape_sitemap(\*\*params) -> BrandWebScrapeSitemapResponse + +# Monitors + +Types: + +```python +from brand.dev.types import WebhookDelivery +``` + +# Batch + +Types: + +```python +from brand.dev.types import PageErrorCount, Failure, CrawlControls, Intake +``` diff --git a/pyproject.toml b/pyproject.toml index 1ac8a24c..8f59f086 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "brand.dev" -version = "1.43.0" +version = "1.44.0" description = "The official Python library for the brand.dev API" dynamic = ["readme"] license = "Apache-2.0" @@ -168,7 +168,7 @@ show_error_codes = true # # We also exclude our `tests` as mypy doesn't always infer # types correctly and Pyright will still catch any type errors. -exclude = ['src/brand/dev/_files.py', '_dev/.*.py', 'tests/.*'] +exclude = ["src/brand/dev/_files.py", "_dev/.*.py", "tests/.*"] strict_equality = true implicit_reexport = true diff --git a/scripts/bootstrap b/scripts/bootstrap index b430fee3..fe8451e4 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response diff --git a/src/brand/dev/_base_client.py b/src/brand/dev/_base_client.py index dc4af6b1..ce73b2f5 100644 --- a/src/brand/dev/_base_client.py +++ b/src/brand/dev/_base_client.py @@ -540,6 +540,10 @@ def _build_request( files = cast(HttpxRequestFiles, ForceMultipartDict()) prepared_url = self._prepare_url(options.url) + # preserve hard-coded query params from the url + if params and prepared_url.query: + params = {**dict(prepared_url.params.items()), **params} + prepared_url = prepared_url.copy_with(raw_path=prepared_url.raw_path.split(b"?", 1)[0]) if "_" in prepared_url.host: # work around https://github.com/encode/httpx/discussions/2880 kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")} diff --git a/src/brand/dev/_client.py b/src/brand/dev/_client.py index 5b46246f..fa051a57 100644 --- a/src/brand/dev/_client.py +++ b/src/brand/dev/_client.py @@ -19,7 +19,11 @@ RequestOptions, not_given, ) -from ._utils import is_given, get_async_library +from ._utils import ( + is_given, + is_mapping_t, + get_async_library, +) from ._compat import cached_property from ._version import __version__ from ._streaming import Stream as Stream, AsyncStream as AsyncStream @@ -90,6 +94,15 @@ def __init__( if base_url is None: base_url = f"https://api.brand.dev/v1" + custom_headers_env = os.environ.get("BRAND_DEV_CUSTOM_HEADERS") + if custom_headers_env is not None: + parsed: dict[str, str] = {} + for line in custom_headers_env.split("\n"): + colon = line.find(":") + if colon >= 0: + parsed[line[:colon].strip()] = line[colon + 1 :].strip() + default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} + super().__init__( version=__version__, base_url=base_url, @@ -264,6 +277,15 @@ def __init__( if base_url is None: base_url = f"https://api.brand.dev/v1" + custom_headers_env = os.environ.get("BRAND_DEV_CUSTOM_HEADERS") + if custom_headers_env is not None: + parsed: dict[str, str] = {} + for line in custom_headers_env.split("\n"): + colon = line.find(":") + if colon >= 0: + parsed[line[:colon].strip()] = line[colon + 1 :].strip() + default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} + super().__init__( version=__version__, base_url=base_url, diff --git a/src/brand/dev/_files.py b/src/brand/dev/_files.py index cc14c14f..76da9e08 100644 --- a/src/brand/dev/_files.py +++ b/src/brand/dev/_files.py @@ -3,8 +3,8 @@ import io import os import pathlib -from typing import overload -from typing_extensions import TypeGuard +from typing import Sequence, cast, overload +from typing_extensions import TypeVar, TypeGuard import anyio @@ -17,7 +17,9 @@ HttpxFileContent, HttpxRequestFiles, ) -from ._utils import is_tuple_t, is_mapping_t, is_sequence_t +from ._utils import is_list, is_mapping, is_tuple_t, is_mapping_t, is_sequence_t + +_T = TypeVar("_T") def is_base64_file_input(obj: object) -> TypeGuard[Base64FileInput]: @@ -97,7 +99,7 @@ async def async_to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles elif is_sequence_t(files): files = [(key, await _async_transform_file(file)) for key, file in files] else: - raise TypeError("Unexpected file type input {type(files)}, expected mapping or sequence") + raise TypeError(f"Unexpected file type input {type(files)}, expected mapping or sequence") return files @@ -121,3 +123,51 @@ async def async_read_file_content(file: FileContent) -> HttpxFileContent: return await anyio.Path(file).read_bytes() return file + + +def deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]]) -> _T: + """Copy only the containers along the given paths. + + Used to guard against mutation by extract_files without copying the entire structure. + Only dicts and lists that lie on a path are copied; everything else + is returned by reference. + + For example, given paths=[["foo", "files", "file"]] and the structure: + { + "foo": { + "bar": {"baz": {}}, + "files": {"file": } + } + } + The root dict, "foo", and "files" are copied (they lie on the path). + "bar" and "baz" are returned by reference (off the path). + """ + return _deepcopy_with_paths(item, paths, 0) + + +def _deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]], index: int) -> _T: + if not paths: + return item + if is_mapping(item): + key_to_paths: dict[str, list[Sequence[str]]] = {} + for path in paths: + if index < len(path): + key_to_paths.setdefault(path[index], []).append(path) + + # if no path continues through this mapping, it won't be mutated and copying it is redundant + if not key_to_paths: + return item + + result = dict(item) + for key, subpaths in key_to_paths.items(): + if key in result: + result[key] = _deepcopy_with_paths(result[key], subpaths, index + 1) + return cast(_T, result) + if is_list(item): + array_paths = [path for path in paths if index < len(path) and path[index] == ""] + + # if no path expects a list here, nothing will be mutated inside it - return by reference + if not array_paths: + return cast(_T, item) + return cast(_T, [_deepcopy_with_paths(entry, array_paths, index + 1) for entry in item]) + return item diff --git a/src/brand/dev/_models.py b/src/brand/dev/_models.py index 29070e05..8c5ab260 100644 --- a/src/brand/dev/_models.py +++ b/src/brand/dev/_models.py @@ -25,7 +25,9 @@ ClassVar, Protocol, Required, + Annotated, ParamSpec, + TypeAlias, TypedDict, TypeGuard, final, @@ -79,7 +81,15 @@ from ._constants import RAW_RESPONSE_HEADER if TYPE_CHECKING: + from pydantic import GetCoreSchemaHandler, ValidatorFunctionWrapHandler + from pydantic_core import CoreSchema, core_schema from pydantic_core.core_schema import ModelField, ModelSchema, LiteralSchema, ModelFieldsSchema +else: + try: + from pydantic_core import CoreSchema, core_schema + except ImportError: + CoreSchema = None + core_schema = None __all__ = ["BaseModel", "GenericModel"] @@ -396,6 +406,76 @@ def model_dump_json( ) +class _EagerIterable(list[_T], Generic[_T]): + """ + Accepts any Iterable[T] input (including generators), consumes it + eagerly, and validates all items upfront. + + Validation preserves the original container type where possible + (e.g. a set[T] stays a set[T]). Serialization (model_dump / JSON) + always emits a list — round-tripping through model_dump() will not + restore the original container type. + """ + + @classmethod + def __get_pydantic_core_schema__( + cls, + source_type: Any, + handler: GetCoreSchemaHandler, + ) -> CoreSchema: + (item_type,) = get_args(source_type) or (Any,) + item_schema: CoreSchema = handler.generate_schema(item_type) + list_of_items_schema: CoreSchema = core_schema.list_schema(item_schema) + + return core_schema.no_info_wrap_validator_function( + cls._validate, + list_of_items_schema, + serialization=core_schema.plain_serializer_function_ser_schema( + cls._serialize, + info_arg=False, + ), + ) + + @staticmethod + def _validate(v: Iterable[_T], handler: "ValidatorFunctionWrapHandler") -> Any: + original_type: type[Any] = type(v) + + # Normalize to list so list_schema can validate each item + if isinstance(v, list): + items: list[_T] = v + else: + try: + items = list(v) + except TypeError as e: + raise TypeError("Value is not iterable") from e + + # Validate items against the inner schema + validated: list[_T] = handler(items) + + # Reconstruct original container type + if original_type is list: + return validated + # str(list) produces the list's repr, not a string built from items, + # so skip reconstruction for str and its subclasses. + if issubclass(original_type, str): + return validated + try: + return original_type(validated) + except (TypeError, ValueError): + # If the type cannot be reconstructed, just return the validated list + return validated + + @staticmethod + def _serialize(v: Iterable[_T]) -> list[_T]: + """Always serialize as a list so Pydantic's JSON encoder is happy.""" + if isinstance(v, list): + return v + return list(v) + + +EagerIterable: TypeAlias = Annotated[Iterable[_T], _EagerIterable] + + def _construct_field(value: object, field: FieldInfo, key: str) -> object: if value is None: return field_get_default(field) diff --git a/src/brand/dev/_qs.py b/src/brand/dev/_qs.py index de8c99bc..4127c19c 100644 --- a/src/brand/dev/_qs.py +++ b/src/brand/dev/_qs.py @@ -2,17 +2,13 @@ from typing import Any, List, Tuple, Union, Mapping, TypeVar from urllib.parse import parse_qs, urlencode -from typing_extensions import Literal, get_args +from typing_extensions import get_args -from ._types import NotGiven, not_given +from ._types import NotGiven, ArrayFormat, NestedFormat, not_given from ._utils import flatten _T = TypeVar("_T") - -ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] -NestedFormat = Literal["dots", "brackets"] - PrimitiveData = Union[str, int, float, bool, None] # this should be Data = Union[PrimitiveData, "List[Data]", "Tuple[Data]", "Mapping[str, Data]"] # https://github.com/microsoft/pyright/issues/3555 diff --git a/src/brand/dev/_types.py b/src/brand/dev/_types.py index fce564e0..eff6aae2 100644 --- a/src/brand/dev/_types.py +++ b/src/brand/dev/_types.py @@ -47,6 +47,9 @@ ModelT = TypeVar("ModelT", bound=pydantic.BaseModel) _T = TypeVar("_T") +ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] +NestedFormat = Literal["dots", "brackets"] + # Approximates httpx internal ProxiesTypes and RequestFiles types # while adding support for `PathLike` instances diff --git a/src/brand/dev/_utils/__init__.py b/src/brand/dev/_utils/__init__.py index 10cb66d2..1c090e51 100644 --- a/src/brand/dev/_utils/__init__.py +++ b/src/brand/dev/_utils/__init__.py @@ -24,7 +24,6 @@ coerce_integer as coerce_integer, file_from_path as file_from_path, strip_not_given as strip_not_given, - deepcopy_minimal as deepcopy_minimal, get_async_library as get_async_library, maybe_coerce_float as maybe_coerce_float, get_required_header as get_required_header, diff --git a/src/brand/dev/_utils/_utils.py b/src/brand/dev/_utils/_utils.py index eec7f4a1..199cd231 100644 --- a/src/brand/dev/_utils/_utils.py +++ b/src/brand/dev/_utils/_utils.py @@ -17,11 +17,11 @@ ) from pathlib import Path from datetime import date, datetime -from typing_extensions import TypeGuard +from typing_extensions import TypeGuard, get_args import sniffio -from .._types import Omit, NotGiven, FileTypes, HeadersLike +from .._types import Omit, NotGiven, FileTypes, ArrayFormat, HeadersLike _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) @@ -40,25 +40,45 @@ def extract_files( query: Mapping[str, object], *, paths: Sequence[Sequence[str]], + array_format: ArrayFormat = "brackets", ) -> list[tuple[str, FileTypes]]: """Recursively extract files from the given dictionary based on specified paths. A path may look like this ['foo', 'files', '', 'data']. + ``array_format`` controls how ```` segments contribute to the emitted + field name. Supported values: ``"brackets"`` (``foo[]``), ``"repeat"`` and + ``"comma"`` (``foo``), ``"indices"`` (``foo[0]``, ``foo[1]``). + Note: this mutates the given dictionary. """ files: list[tuple[str, FileTypes]] = [] for path in paths: - files.extend(_extract_items(query, path, index=0, flattened_key=None)) + files.extend(_extract_items(query, path, index=0, flattened_key=None, array_format=array_format)) return files +def _array_suffix(array_format: ArrayFormat, array_index: int) -> str: + if array_format == "brackets": + return "[]" + if array_format == "indices": + return f"[{array_index}]" + if array_format == "repeat" or array_format == "comma": + # Both repeat the bare field name for each file part; there is no + # meaningful way to comma-join binary parts. + return "" + raise NotImplementedError( + f"Unknown array_format value: {array_format}, choose from {', '.join(get_args(ArrayFormat))}" + ) + + def _extract_items( obj: object, path: Sequence[str], *, index: int, flattened_key: str | None, + array_format: ArrayFormat, ) -> list[tuple[str, FileTypes]]: try: key = path[index] @@ -75,9 +95,11 @@ def _extract_items( if is_list(obj): files: list[tuple[str, FileTypes]] = [] - for entry in obj: - assert_is_file_content(entry, key=flattened_key + "[]" if flattened_key else "") - files.append((flattened_key + "[]", cast(FileTypes, entry))) + for array_index, entry in enumerate(obj): + suffix = _array_suffix(array_format, array_index) + emitted_key = (flattened_key + suffix) if flattened_key else suffix + assert_is_file_content(entry, key=emitted_key) + files.append((emitted_key, cast(FileTypes, entry))) return files assert_is_file_content(obj, key=flattened_key) @@ -86,8 +108,9 @@ def _extract_items( index += 1 if is_dict(obj): try: - # We are at the last entry in the path so we must remove the field - if (len(path)) == index: + # Remove the field if there are no more dict keys in the path, + # only "" traversal markers or end. + if all(p == "" for p in path[index:]): item = obj.pop(key) else: item = obj[key] @@ -105,6 +128,7 @@ def _extract_items( path, index=index, flattened_key=flattened_key, + array_format=array_format, ) elif is_list(obj): if key != "": @@ -116,9 +140,12 @@ def _extract_items( item, path, index=index, - flattened_key=flattened_key + "[]" if flattened_key is not None else "[]", + flattened_key=( + (flattened_key if flattened_key is not None else "") + _array_suffix(array_format, array_index) + ), + array_format=array_format, ) - for item in obj + for array_index, item in enumerate(obj) ] ) @@ -176,21 +203,6 @@ def is_iterable(obj: object) -> TypeGuard[Iterable[object]]: return isinstance(obj, Iterable) -def deepcopy_minimal(item: _T) -> _T: - """Minimal reimplementation of copy.deepcopy() that will only copy certain object types: - - - mappings, e.g. `dict` - - list - - This is done for performance reasons. - """ - if is_mapping(item): - return cast(_T, {k: deepcopy_minimal(v) for k, v in item.items()}) - if is_list(item): - return cast(_T, [deepcopy_minimal(entry) for entry in item]) - return item - - # copied from https://github.com/Rapptz/RoboDanny def human_join(seq: Sequence[str], *, delim: str = ", ", final: str = "or") -> str: size = len(seq) diff --git a/src/brand/dev/_version.py b/src/brand/dev/_version.py index 6c398c02..236a1892 100644 --- a/src/brand/dev/_version.py +++ b/src/brand/dev/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "brand.dev" -__version__ = "1.43.0" # x-release-please-version +__version__ = "1.44.0" # x-release-please-version diff --git a/src/brand/dev/resources/brand.py b/src/brand/dev/resources/brand.py index 856a4904..5932271a 100644 --- a/src/brand/dev/resources/brand.py +++ b/src/brand/dev/resources/brand.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Iterable +from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal, overload import httpx @@ -29,7 +29,7 @@ brand_retrieve_simplified_params, brand_identify_from_transaction_params, ) -from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from .._utils import required_args, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -87,66 +87,212 @@ def with_streaming_response(self) -> BrandResourceWithStreamingResponse: def retrieve( self, *, - domain: str, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + domain: str | Omit = omit, + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] + ] + | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + name: str | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + ticker: str | Omit = omit, + ticker_exchange: Literal[ + "AMEX", + "AMS", + "AQS", + "ASX", + "ATH", + "BER", + "BME", + "BRU", + "BSE", + "BUD", + "BUE", + "BVC", + "CBOE", + "CNQ", + "CPH", + "DFM", + "DOH", + "DUB", + "DUS", + "DXE", + "EGX", + "FSX", + "HAM", + "HEL", + "HKSE", + "HOSE", + "ICE", + "IOB", + "IST", + "JKT", + "JNB", + "JPX", + "KLS", + "KOE", + "KSC", + "KUW", + "LIS", + "LSE", + "MCX", + "MEX", + "MIL", + "MUN", + "NASDAQ", + "NEO", + "NSE", + "NYSE", + "NZE", + "OSL", + "OTC", + "PAR", + "PNK", + "PRA", + "RIS", + "SAO", + "SAU", + "SES", + "SET", + "SGO", + "SHH", + "SHZ", + "SIX", + "STO", + "STU", + "TAI", + "TAL", + "TLV", + "TSX", + "TSXV", + "TWO", + "VIE", + "WSE", + "XETRA", ] | Omit = omit, - max_speed: bool | Omit = omit, timeout_ms: int | 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. @@ -163,13 +309,29 @@ def retrieve( domain: Domain name to retrieve brand data for (e.g., 'example.com', 'google.com'). Cannot be used with name or ticker parameters. - force_language: Optional parameter to force the language of the retrieved brand data. Works with - all three lookup methods. + force_language: Language to force for the retrieved brand data. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. Works with all three lookup methods. + name: Company name to retrieve brand data for (e.g., 'Apple Inc'). Cannot be used with + domain or ticker parameters. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + ticker: Stock ticker symbol to retrieve brand data for (e.g., 'AAPL'). Cannot be used + with domain or name parameters. + + ticker_exchange: Stock exchange code. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -193,7 +355,12 @@ def retrieve( { "domain": domain, "force_language": force_language, + "max_age_ms": max_age_ms, "max_speed": max_speed, + "name": name, + "tags": tags, + "ticker": ticker, + "ticker_exchange": ticker_exchange, "timeout_ms": timeout_ms, }, brand_retrieve_params.BrandRetrieveParams, @@ -206,6 +373,8 @@ def ai_product( self, *, url: str, + max_age_ms: int | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -215,15 +384,21 @@ def ai_product( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandAIProductResponse: """ - Beta feature: Given a single URL, determines if it is a product detail page, - classifies the platform/product type, and extracts the product information. - Supports Amazon, TikTok Shop, Etsy, and generic ecommerce sites. + Given a single URL, determines if it is a product page and extracts the product + information. Args: url: The product page URL to extract product data from. - timeout_ms: Optional timeout in milliseconds for the request. Maximum allowed value is - 300000ms (5 minutes). + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 7 days (604800000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). extra_headers: Send extra headers @@ -238,6 +413,8 @@ def ai_product( body=maybe_transform( { "url": url, + "max_age_ms": max_age_ms, + "tags": tags, "timeout_ms": timeout_ms, }, brand_ai_product_params.BrandAIProductParams, @@ -253,7 +430,9 @@ def ai_products( self, *, domain: str, + max_age_ms: int | Omit = omit, max_products: int | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -262,19 +441,26 @@ def ai_products( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandAIProductsResponse: - """Beta feature: Extract product information from a brand's website. + """Extract product information from a brand's website. - We will - analyze the website and return a list of products with details such as name, - description, image, pricing, features, and more. + We will analyze the website + and return a list of products with details such as name, description, image, + pricing, features, and more. Args: domain: The domain name to analyze. + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 7 days (604800000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + max_products: Maximum number of products to extract. - timeout_ms: Optional timeout in milliseconds for the request. Maximum allowed value is - 300000ms (5 minutes). + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). extra_headers: Send extra headers @@ -291,7 +477,9 @@ def ai_products( self, *, direct_url: str, + max_age_ms: int | Omit = omit, max_products: int | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -300,20 +488,27 @@ def ai_products( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandAIProductsResponse: - """Beta feature: Extract product information from a brand's website. + """Extract product information from a brand's website. - We will - analyze the website and return a list of products with details such as name, - description, image, pricing, features, and more. + We will analyze the website + and return a list of products with details such as name, description, image, + pricing, features, and more. Args: direct_url: A specific URL to use directly as the starting point for extraction without domain resolution. + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 7 days (604800000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + max_products: Maximum number of products to extract. - timeout_ms: Optional timeout in milliseconds for the request. Maximum allowed value is - 300000ms (5 minutes). + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). extra_headers: Send extra headers @@ -330,7 +525,9 @@ def ai_products( self, *, domain: str | Omit = omit, + max_age_ms: int | Omit = omit, max_products: int | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | Omit = omit, direct_url: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -345,7 +542,9 @@ def ai_products( body=maybe_transform( { "domain": domain, + "max_age_ms": max_age_ms, "max_products": max_products, + "tags": tags, "timeout_ms": timeout_ms, "direct_url": direct_url, }, @@ -363,6 +562,7 @@ def ai_query( data_to_extract: Iterable[brand_ai_query_params.DataToExtract], domain: str, specific_pages: brand_ai_query_params.SpecificPages | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -384,6 +584,8 @@ def ai_query( specific_pages: Optional object specifying which pages to analyze + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -403,6 +605,7 @@ def ai_query( "data_to_extract": data_to_extract, "domain": domain, "specific_pages": specific_pages, + "tags": tags, "timeout_ms": timeout_ms, }, brand_ai_query_params.BrandAIQueryParams, @@ -416,7 +619,10 @@ def ai_query( def fonts( self, *, - domain: str, + direct_url: str | Omit = omit, + domain: str | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -426,12 +632,26 @@ def fonts( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandFontsResponse: """ - Extract font information from a brand's website including font families, usage + Scrape font information from a website including font families, usage statistics, fallbacks, and element/word counts. Args: + direct_url: A specific URL to fetch fonts from directly, bypassing domain resolution (e.g., + 'https://example.com/design-system'). When provided, fonts are extracted from + this exact URL. You must provide either 'domain' or 'directUrl', but not both. + domain: Domain name to extract fonts from (e.g., 'example.com', 'google.com'). The - domain will be automatically normalized and validated. + domain will be automatically normalized and validated. You must provide either + 'domain' or 'directUrl', but not both. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed @@ -446,7 +666,7 @@ def fonts( timeout: Override the client-level default timeout for this request, in seconds """ return self._get( - "/brand/fonts", + "/web/fonts", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -454,7 +674,10 @@ def fonts( timeout=timeout, query=maybe_transform( { + "direct_url": direct_url, "domain": domain, + "max_age_ms": max_age_ms, + "tags": tags, "timeout_ms": timeout_ms, }, brand_fonts_params.BrandFontsParams, @@ -469,309 +692,377 @@ def identify_from_transaction( transaction_info: str, city: str | Omit = omit, country_gl: Literal[ - "ad", - "ae", "af", - "ag", - "ai", "al", - "am", - "an", + "dz", + "as", + "ad", "ao", + "ai", "aq", + "ag", "ar", - "as", - "at", - "au", + "am", "aw", + "au", + "at", "az", - "ba", - "bb", + "bs", + "bh", "bd", + "bb", + "by", "be", - "bf", - "bg", - "bh", - "bi", + "bz", "bj", "bm", - "bn", - "bo", - "br", - "bs", "bt", - "bv", + "bo", + "ba", "bw", - "by", - "bz", + "bv", + "br", + "io", + "bn", + "bg", + "bf", + "bi", + "kh", + "cm", "ca", - "cc", - "cd", + "cv", + "ky", "cf", - "cg", - "ch", - "ci", - "ck", + "td", "cl", - "cm", "cn", + "cx", + "cc", "co", + "km", + "cg", + "cd", + "ck", "cr", + "ci", + "hr", "cu", - "cv", - "cx", "cy", "cz", - "de", - "dj", "dk", + "dj", "dm", "do", - "dz", "ec", - "ee", "eg", - "eh", + "sv", + "gq", "er", - "es", + "ee", "et", - "fi", - "fj", "fk", - "fm", "fo", + "fj", + "fi", "fr", + "gf", + "pf", + "tf", "ga", - "gb", - "gd", + "gm", "ge", - "gf", + "de", "gh", "gi", + "gr", "gl", - "gm", - "gn", + "gd", "gp", - "gq", - "gr", - "gs", - "gt", "gu", + "gt", + "gn", "gw", "gy", - "hk", + "ht", "hm", + "va", "hn", - "hr", - "ht", + "hk", "hu", + "is", + "in", "id", + "ir", + "iq", "ie", "il", - "in", - "io", - "iq", - "ir", - "is", "it", "jm", - "jo", "jp", + "jo", + "kz", "ke", - "kg", - "kh", "ki", - "km", - "kn", "kp", "kr", "kw", - "ky", - "kz", + "kg", "la", + "lv", "lb", - "lc", - "li", - "lk", - "lr", "ls", + "lr", + "ly", + "li", "lt", "lu", - "lv", - "ly", - "ma", - "mc", - "md", - "mg", - "mh", + "mo", "mk", + "mg", + "mw", + "my", + "mv", "ml", - "mm", - "mn", - "mo", - "mp", + "mt", + "mh", "mq", "mr", - "ms", - "mt", "mu", - "mv", - "mw", + "yt", "mx", - "my", + "fm", + "md", + "mc", + "mn", + "ms", + "ma", "mz", + "mm", "na", + "nr", + "np", + "nl", + "an", "nc", + "nz", + "ni", "ne", - "nf", "ng", - "ni", - "nl", - "no", - "np", - "nr", "nu", - "nz", + "nf", + "mp", + "no", "om", + "pk", + "pw", + "ps", "pa", - "pe", - "pf", "pg", + "py", + "pe", "ph", - "pk", - "pl", - "pm", "pn", - "pr", - "ps", + "pl", "pt", - "pw", - "py", + "pr", "qa", "re", "ro", - "rs", "ru", "rw", + "sh", + "kn", + "lc", + "pm", + "vc", + "ws", + "sm", + "st", "sa", - "sb", + "sn", + "rs", "sc", - "sd", - "se", + "sl", "sg", - "sh", - "si", - "sj", "sk", - "sl", - "sm", - "sn", + "si", + "sb", "so", + "za", + "gs", + "es", + "lk", + "sd", "sr", - "st", - "sv", - "sy", + "sj", "sz", - "tc", - "td", - "tf", - "tg", - "th", + "se", + "ch", + "sy", + "tw", "tj", - "tk", + "tz", + "th", "tl", - "tm", - "tn", + "tg", + "tk", "to", - "tr", "tt", + "tn", + "tr", + "tm", + "tc", "tv", - "tw", - "tz", - "ua", "ug", - "um", + "ua", + "ae", + "gb", "us", + "um", "uy", "uz", - "va", - "vc", + "vu", "ve", + "vn", "vg", "vi", - "vn", - "vu", "wf", - "ws", + "eh", "ye", - "yt", - "za", "zm", "zw", ] | Omit = omit, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] | Omit = omit, - high_confidence_only: bool | Omit = omit, - max_speed: bool | Omit = omit, - mcc: str | Omit = omit, - phone: float | Omit = omit, + high_confidence_only: Union[bool, Literal["true", "false"]] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + mcc: Union[str, float] | Omit = omit, + phone: Union[str, float] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -789,14 +1080,13 @@ def identify_from_transaction( city: Optional city name to prioritize when searching for the brand. - country_gl: Optional country code (GL parameter) to specify the country. This affects the - geographic location used for search queries. + country_gl: Two-letter ISO 3166-1 alpha-2 country code (GL parameter) used to localize + search. - force_language: Optional parameter to force the language of the retrieved brand data. + force_language: Language to force for the retrieved brand data. high_confidence_only: When set to true, the API will perform an additional verification steps to ensure the identified brand matches the transaction with high confidence. - Defaults to false. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of @@ -807,6 +1097,10 @@ def identify_from_transaction( phone: Optional phone number from the transaction to help verify brand match. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -836,6 +1130,7 @@ def identify_from_transaction( "max_speed": max_speed, "mcc": mcc, "phone": phone, + "tags": tags, "timeout_ms": timeout_ms, }, brand_identify_from_transaction_params.BrandIdentifyFromTransactionParams, @@ -848,6 +1143,7 @@ def prefetch( self, *, domain: str, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -858,13 +1154,13 @@ def prefetch( ) -> BrandPrefetchResponse: """ Signal that you may fetch brand data for a particular domain soon to improve - latency. This endpoint does not charge credits and is available for paid - customers to optimize future requests. [You must be on a paid plan to use this - endpoint] + latency. Args: domain: Domain name to prefetch brand data for + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -882,6 +1178,7 @@ def prefetch( body=maybe_transform( { "domain": domain, + "tags": tags, "timeout_ms": timeout_ms, }, brand_prefetch_params.BrandPrefetchParams, @@ -896,6 +1193,7 @@ def prefetch_by_email( self, *, email: str, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -908,15 +1206,15 @@ def prefetch_by_email( Signal that you may fetch brand data for a particular domain soon to improve latency. This endpoint accepts an email address, extracts the domain from it, validates that it's not a disposable or free email provider, and queues the - domain for prefetching. This endpoint does not charge credits and is available - for paid customers to optimize future requests. [You must be on a paid plan to - use this endpoint] + domain for prefetching. Args: email: Email address to prefetch brand data for. The domain will be extracted from the email. Free email providers (gmail.com, yahoo.com, etc.) and disposable email addresses are not allowed. + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -934,6 +1232,7 @@ def prefetch_by_email( body=maybe_transform( { "email": email, + "tags": tags, "timeout_ms": timeout_ms, }, brand_prefetch_by_email_params.BrandPrefetchByEmailParams, @@ -948,65 +1247,134 @@ def retrieve_by_email( self, *, email: str, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] | Omit = omit, - max_speed: bool | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -1017,21 +1385,29 @@ def retrieve_by_email( ) -> BrandRetrieveByEmailResponse: """ Retrieve brand information using an email address while detecting disposable and - free email addresses. This endpoint extracts the domain from the email address - and returns brand data for that domain. Disposable and free email addresses - (like gmail.com, yahoo.com) will throw a 422 error. + free email addresses. Disposable and free email addresses (like gmail.com, + yahoo.com) will throw a 422 error. Args: email: Email address to retrieve brand data for (e.g., 'contact@example.com'). The domain will be extracted from the email. Free email providers (gmail.com, yahoo.com, etc.) and disposable email addresses are not allowed. - force_language: Optional parameter to force the language of the retrieved brand data. + force_language: Language to force for the retrieved brand data. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -1055,7 +1431,9 @@ def retrieve_by_email( { "email": email, "force_language": force_language, + "max_age_ms": max_age_ms, "max_speed": max_speed, + "tags": tags, "timeout_ms": timeout_ms, }, brand_retrieve_by_email_params.BrandRetrieveByEmailParams, @@ -1068,65 +1446,134 @@ def retrieve_by_isin( self, *, isin: str, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] | Omit = omit, - max_speed: bool | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -1137,20 +1584,28 @@ def retrieve_by_isin( ) -> BrandRetrieveByIsinResponse: """ Retrieve brand information using an ISIN (International Securities - Identification Number). This endpoint looks up the company associated with the - ISIN and returns its brand data. + Identification Number). Args: isin: ISIN (International Securities Identification Number) to retrieve brand data for (e.g., 'AU000000IMD5', 'US0378331005'). Must be exactly 12 characters: 2 letters followed by 9 alphanumeric characters and ending with a digit. - force_language: Optional parameter to force the language of the retrieved brand data. + force_language: Language to force for the retrieved brand data. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -1174,7 +1629,9 @@ def retrieve_by_isin( { "isin": isin, "force_language": force_language, + "max_age_ms": max_age_ms, "max_speed": max_speed, + "tags": tags, "timeout_ms": timeout_ms, }, brand_retrieve_by_isin_params.BrandRetrieveByIsinParams, @@ -1188,306 +1645,375 @@ def retrieve_by_name( *, name: str, country_gl: Literal[ - "ad", - "ae", "af", - "ag", - "ai", "al", - "am", - "an", + "dz", + "as", + "ad", "ao", + "ai", "aq", + "ag", "ar", - "as", - "at", - "au", + "am", "aw", + "au", + "at", "az", - "ba", - "bb", + "bs", + "bh", "bd", + "bb", + "by", "be", - "bf", - "bg", - "bh", - "bi", + "bz", "bj", "bm", - "bn", - "bo", - "br", - "bs", "bt", - "bv", + "bo", + "ba", "bw", - "by", - "bz", + "bv", + "br", + "io", + "bn", + "bg", + "bf", + "bi", + "kh", + "cm", "ca", - "cc", - "cd", + "cv", + "ky", "cf", - "cg", - "ch", - "ci", - "ck", + "td", "cl", - "cm", "cn", + "cx", + "cc", "co", + "km", + "cg", + "cd", + "ck", "cr", + "ci", + "hr", "cu", - "cv", - "cx", "cy", "cz", - "de", - "dj", "dk", + "dj", "dm", "do", - "dz", "ec", - "ee", "eg", - "eh", + "sv", + "gq", "er", - "es", + "ee", "et", - "fi", - "fj", "fk", - "fm", "fo", + "fj", + "fi", "fr", + "gf", + "pf", + "tf", "ga", - "gb", - "gd", + "gm", "ge", - "gf", + "de", "gh", "gi", + "gr", "gl", - "gm", - "gn", + "gd", "gp", - "gq", - "gr", - "gs", - "gt", "gu", + "gt", + "gn", "gw", "gy", - "hk", + "ht", "hm", + "va", "hn", - "hr", - "ht", + "hk", "hu", + "is", + "in", "id", + "ir", + "iq", "ie", "il", - "in", - "io", - "iq", - "ir", - "is", "it", "jm", - "jo", "jp", + "jo", + "kz", "ke", - "kg", - "kh", "ki", - "km", - "kn", "kp", "kr", "kw", - "ky", - "kz", + "kg", "la", + "lv", "lb", - "lc", - "li", - "lk", - "lr", "ls", - "lt", - "lu", - "lv", + "lr", "ly", - "ma", - "mc", - "md", - "mg", - "mh", + "li", + "lt", + "lu", + "mo", "mk", + "mg", + "mw", + "my", + "mv", "ml", - "mm", - "mn", - "mo", - "mp", + "mt", + "mh", "mq", "mr", - "ms", - "mt", "mu", - "mv", - "mw", + "yt", "mx", - "my", + "fm", + "md", + "mc", + "mn", + "ms", + "ma", "mz", + "mm", "na", + "nr", + "np", + "nl", + "an", "nc", + "nz", + "ni", "ne", - "nf", "ng", - "ni", - "nl", - "no", - "np", - "nr", "nu", - "nz", + "nf", + "mp", + "no", "om", + "pk", + "pw", + "ps", "pa", - "pe", - "pf", "pg", + "py", + "pe", "ph", - "pk", - "pl", - "pm", "pn", - "pr", - "ps", + "pl", "pt", - "pw", - "py", + "pr", "qa", "re", "ro", - "rs", "ru", "rw", + "sh", + "kn", + "lc", + "pm", + "vc", + "ws", + "sm", + "st", "sa", - "sb", + "sn", + "rs", "sc", - "sd", - "se", + "sl", "sg", - "sh", - "si", - "sj", "sk", - "sl", - "sm", - "sn", + "si", + "sb", "so", + "za", + "gs", + "es", + "lk", + "sd", "sr", - "st", - "sv", - "sy", + "sj", "sz", - "tc", - "td", - "tf", - "tg", - "th", + "se", + "ch", + "sy", + "tw", "tj", - "tk", + "tz", + "th", "tl", - "tm", - "tn", + "tg", + "tk", "to", - "tr", "tt", + "tn", + "tr", + "tm", + "tc", "tv", - "tw", - "tz", - "ua", "ug", - "um", + "ua", + "ae", + "gb", "us", + "um", "uy", "uz", - "va", - "vc", + "vu", "ve", + "vn", "vg", "vi", - "vn", - "vu", "wf", - "ws", + "eh", "ye", - "yt", - "za", "zm", "zw", ] | Omit = omit, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] | Omit = omit, - max_speed: bool | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -1496,24 +2022,31 @@ def retrieve_by_name( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandRetrieveByNameResponse: - """Retrieve brand information using a company name. - - This endpoint searches for the - company by name and returns its brand data. + """ + Retrieve brand information using a company name. Args: name: Company name to retrieve brand data for (e.g., 'Apple Inc', 'Microsoft Corporation'). Must be 3-30 characters. - country_gl: Optional country code (GL parameter) to specify the country. This affects the - geographic location used for search queries. + country_gl: Two-letter ISO 3166-1 alpha-2 country code (GL parameter) used to localize + search. + + force_language: Language to force for the retrieved brand data. - force_language: Optional parameter to force the language of the retrieved brand data. + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -1538,7 +2071,9 @@ def retrieve_by_name( "name": name, "country_gl": country_gl, "force_language": force_language, + "max_age_ms": max_age_ms, "max_speed": max_speed, + "tags": tags, "timeout_ms": timeout_ms, }, brand_retrieve_by_name_params.BrandRetrieveByNameParams, @@ -1551,65 +2086,134 @@ def retrieve_by_ticker( self, *, ticker: str, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] | Omit = omit, - max_speed: bool | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, ticker_exchange: Literal[ "AMEX", "AMS", @@ -1693,22 +2297,29 @@ def retrieve_by_ticker( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandRetrieveByTickerResponse: - """Retrieve brand information using a stock ticker symbol. - - This endpoint looks up - the company associated with the ticker and returns its brand data. + """ + Retrieve brand information using a stock ticker symbol. Args: ticker: Stock ticker symbol to retrieve brand data for (e.g., 'AAPL', 'GOOGL', 'BRK.A'). Must be 1-15 characters, letters/numbers/dots only. - force_language: Optional parameter to force the language of the retrieved brand data. + force_language: Language to force for the retrieved brand data. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. - ticker_exchange: Optional stock exchange for the ticker. Defaults to NASDAQ if not specified. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + ticker_exchange: Stock exchange code. timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed @@ -1733,7 +2344,9 @@ def retrieve_by_ticker( { "ticker": ticker, "force_language": force_language, + "max_age_ms": max_age_ms, "max_speed": max_speed, + "tags": tags, "ticker_exchange": ticker_exchange, "timeout_ms": timeout_ms, }, @@ -1749,6 +2362,7 @@ def retrieve_naics( input: str, max_results: int | Omit = omit, min_results: int | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -1758,18 +2372,22 @@ def retrieve_naics( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandRetrieveNaicsResponse: """ - Endpoint to classify any brand into a 2022 NAICS code. + Classify any brand into 2022 NAICS industry codes from its domain or name. Args: - input: Brand domain or title to retrieve NAICS code for. If a valid domain is provided - in `input`, it will be used for classification, otherwise, we will search for - the brand using the provided title. + input: Brand domain or title to retrieve NAICS code for. If a valid domain is provided, + it will be used for classification, otherwise, we will search for the brand + using the provided title. max_results: Maximum number of NAICS codes to return. Must be between 1 and 10. Defaults to 5. min_results: Minimum number of NAICS codes to return. Must be at least 1. Defaults to 1. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -1783,7 +2401,7 @@ def retrieve_naics( timeout: Override the client-level default timeout for this request, in seconds """ return self._get( - "/brand/naics", + "/web/naics", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -1794,6 +2412,7 @@ def retrieve_naics( "input": input, "max_results": max_results, "min_results": min_results, + "tags": tags, "timeout_ms": timeout_ms, }, brand_retrieve_naics_params.BrandRetrieveNaicsParams, @@ -1806,6 +2425,9 @@ def retrieve_simplified( self, *, domain: str, + max_age_ms: Optional[int] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + theme: Literal["light", "dark"] | Omit = omit, timeout_ms: int | 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. @@ -1816,12 +2438,23 @@ def retrieve_simplified( ) -> BrandRetrieveSimplifiedResponse: """ Returns a simplified version of brand data containing only essential - information: domain, title, colors, logos, and backdrops. This endpoint is - optimized for faster responses and reduced data transfer. + information: domain, title, colors, logos, and backdrops. Optimized for faster + responses and reduced data transfer. Args: domain: Domain name to retrieve simplified brand data for + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + theme: Optional theme preference used when selecting brand assets. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -1844,6 +2477,9 @@ def retrieve_simplified( query=maybe_transform( { "domain": domain, + "max_age_ms": max_age_ms, + "tags": tags, + "theme": theme, "timeout_ms": timeout_ms, }, brand_retrieve_simplified_params.BrandRetrieveSimplifiedParams, @@ -1855,143 +2491,700 @@ def retrieve_simplified( def screenshot( self, *, - domain: str, - full_screenshot: Literal["true", "false"] | Omit = omit, - page: Literal["login", "signup", "blog", "careers", "pricing", "terms", "privacy", "contact"] | Omit = omit, - prioritize: Literal["speed", "quality"] | 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, - ) -> BrandScreenshotResponse: - """Capture a screenshot of a website. - - Supports both viewport (standard browser - view) and full-page screenshots. Can also screenshot specific page types (login, - pricing, etc.) by using heuristics to find the appropriate URL. Returns a URL to - the uploaded screenshot image hosted on our CDN. - - Args: - domain: Domain name to take screenshot of (e.g., 'example.com', 'google.com'). The - domain will be automatically normalized and validated. - - full_screenshot: Optional parameter to determine screenshot type. If 'true', takes a full page - screenshot capturing all content. If 'false' or not provided, takes a viewport - screenshot (standard browser view). - - page: Optional parameter to specify which page type to screenshot. If provided, the - system will scrape the domain's links and use heuristics to find the most - appropriate URL for the specified page type (30 supported languages). If not - provided, screenshots the main domain landing page. - - prioritize: Optional parameter to prioritize screenshot capture. If 'speed', optimizes for - faster capture with basic quality. If 'quality', optimizes for higher quality - with longer wait times. Defaults to 'quality' if not provided. - - 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 - """ - return self._get( - "/brand/screenshot", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "domain": domain, - "full_screenshot": full_screenshot, - "page": page, - "prioritize": prioritize, - }, - brand_screenshot_params.BrandScreenshotParams, - ), - ), - cast_to=BrandScreenshotResponse, - ) - - def styleguide( - self, - *, - direct_url: str | Omit = omit, - domain: str | Omit = omit, - timeout_ms: int | 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, - ) -> BrandStyleguideResponse: - """ - Automatically extract comprehensive design system information from a brand's - website including colors, typography, spacing, shadows, and UI components. - Either 'domain' or 'directUrl' must be provided as a query parameter, but not - both. - - Args: - direct_url: A specific URL to fetch the styleguide from directly, bypassing domain - resolution (e.g., 'https://example.com/design-system'). - - domain: Domain name to extract styleguide from (e.g., 'example.com', 'google.com'). The - domain will be automatically normalized and validated. - - timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer - than this value, it will be aborted with a 408 status code. Maximum allowed - value is 300000ms (5 minutes). - - 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 - """ - return self._get( - "/brand/styleguide", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "direct_url": direct_url, - "domain": domain, - "timeout_ms": timeout_ms, - }, - brand_styleguide_params.BrandStyleguideParams, - ), - ), - cast_to=BrandStyleguideResponse, - ) - - def web_scrape_html( - self, - *, - url: 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, + color_scheme: Literal["light", "dark"] | Omit = omit, + country: Literal[ + "ad", + "ae", + "af", + "ag", + "ai", + "al", + "am", + "ao", + "ar", + "at", + "au", + "aw", + "az", + "ba", + "bb", + "bd", + "be", + "bf", + "bg", + "bh", + "bi", + "bj", + "bm", + "bn", + "bo", + "bq", + "br", + "bs", + "bw", + "by", + "bz", + "ca", + "cd", + "cf", + "cg", + "ch", + "ci", + "cl", + "cm", + "cn", + "co", + "cr", + "cv", + "cw", + "cy", + "cz", + "de", + "dj", + "dk", + "dm", + "do", + "dz", + "ec", + "ee", + "eg", + "es", + "et", + "fi", + "fj", + "fr", + "ga", + "gb", + "gd", + "ge", + "gf", + "gg", + "gh", + "gm", + "gn", + "gp", + "gq", + "gr", + "gt", + "gu", + "gw", + "gy", + "hk", + "hn", + "hr", + "ht", + "hu", + "id", + "ie", + "il", + "im", + "in", + "iq", + "ir", + "is", + "it", + "je", + "jm", + "jo", + "jp", + "ke", + "kg", + "kh", + "kn", + "kr", + "kw", + "ky", + "kz", + "la", + "lb", + "lc", + "lk", + "lr", + "ls", + "lt", + "lu", + "lv", + "ly", + "ma", + "mc", + "md", + "me", + "mf", + "mg", + "mk", + "ml", + "mm", + "mn", + "mo", + "mq", + "mr", + "mt", + "mu", + "mv", + "mw", + "mx", + "my", + "mz", + "na", + "nc", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nz", + "om", + "pa", + "pe", + "pf", + "pg", + "ph", + "pk", + "pl", + "pr", + "ps", + "pt", + "py", + "qa", + "re", + "ro", + "rs", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sr", + "ss", + "st", + "sv", + "sx", + "sy", + "sz", + "tc", + "td", + "tg", + "th", + "tj", + "tl", + "tm", + "tn", + "tr", + "tt", + "tw", + "tz", + "ua", + "ug", + "us", + "uy", + "uz", + "vc", + "ve", + "vg", + "vi", + "vn", + "ye", + "yt", + "za", + "zm", + "zw", + ] + | Omit = omit, + direct_url: str | Omit = omit, + domain: str | Omit = omit, + full_screenshot: Literal["true", "false"] | Omit = omit, + handle_cookie_popup: Union[bool, Literal["true", "false"]] | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + page: Literal["login", "signup", "blog", "careers", "pricing", "terms", "privacy", "contact"] | Omit = omit, + scroll_offset: Optional[int] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + timeout_ms: int | Omit = omit, + viewport: brand_screenshot_params.Viewport | Omit = omit, + wait_for_ms: Optional[int] | Omit = omit, + zdr: Literal["enabled", "disabled"] | 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, + ) -> BrandScreenshotResponse: + """ + Capture a screenshot of a website. + + Args: + color_scheme: Optional parameter to choose the site's visual theme in the screenshot. Use + 'light' or 'dark' when the site offers both appearances. + + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). + + direct_url: A specific URL to screenshot directly, bypassing domain resolution (e.g., + 'https://example.com/pricing'). When provided, the screenshot is taken of this + exact URL. You must provide either 'domain' or 'directUrl', but not both. + + domain: Domain name to take screenshot of (e.g., 'example.com', 'google.com'). The + domain will be automatically normalized and validated. You must provide either + 'domain' or 'directUrl', but not both. + + full_screenshot: Optional parameter to determine screenshot type. If 'true', takes a full page + screenshot capturing all content. If 'false' or not provided, takes a viewport + screenshot (standard browser view). + + handle_cookie_popup: Optional parameter to control cookie/consent popup handling. If 'true', we + dismiss cookie banner before capture. If 'false' or not provided, captures the + page without that step. + + max_age_ms: Return a cached screenshot if a prior screenshot for the same parameters exists + and is younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always capture fresh. + + page: Optional parameter to specify which page type to screenshot. If provided, the + system will scrape the domain's links and use heuristics to find the most + appropriate URL for the specified page type (30 supported languages). If not + provided, screenshots the main domain landing page. Only applicable when using + 'domain', not 'directUrl'. + + scroll_offset: Optional vertical scroll offset in pixels for capturing a long page in + viewport-sized chunks. When provided, the full page is captured once and the + returned image is the viewport-sized slice that begins at this Y offset (e.g. + request scrollOffset=0, then 1080, then 2160 to walk a 1920x1080 landing page + top to bottom). The final slice may be shorter than the viewport height. Takes + precedence over fullScreenshot. Max: 100000. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). + + viewport: Optional browser viewport dimensions for the screenshot. Defaults to 1920x1080. + + wait_for_ms: Optional browser wait time in milliseconds after initial page load before taking + the screenshot. Min: 0. Max: 30000 (30 seconds). Defaults to 3000 ms when + omitted. + + zdr: Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. + + 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 + """ + return self._get( + "/web/screenshot", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "color_scheme": color_scheme, + "country": country, + "direct_url": direct_url, + "domain": domain, + "full_screenshot": full_screenshot, + "handle_cookie_popup": handle_cookie_popup, + "max_age_ms": max_age_ms, + "page": page, + "scroll_offset": scroll_offset, + "tags": tags, + "timeout_ms": timeout_ms, + "viewport": viewport, + "wait_for_ms": wait_for_ms, + "zdr": zdr, + }, + brand_screenshot_params.BrandScreenshotParams, + ), + ), + cast_to=BrandScreenshotResponse, + ) + + def styleguide( + self, + *, + color_scheme: Literal["light", "dark"] | Omit = omit, + direct_url: str | Omit = omit, + domain: str | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + timeout_ms: int | 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, + ) -> BrandStyleguideResponse: + """ + Extract a comprehensive design system from a website including colors, + typography, spacing, shadows, and UI components. + + Args: + color_scheme: Optional browser color scheme to emulate for websites that respond to + prefers-color-scheme. This value is part of the styleguide cache key. + + direct_url: A specific URL to fetch the styleguide from directly, bypassing domain + resolution (e.g., 'https://example.com/design-system'). When provided, the + styleguide is extracted from this exact URL. You must provide either 'domain' or + 'directUrl', but not both. + + domain: Domain name to extract styleguide from (e.g., 'example.com', 'google.com'). The + domain will be automatically normalized and validated. You must provide either + 'domain' or 'directUrl', but not both. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). + + 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 + """ + return self._get( + "/web/styleguide", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "color_scheme": color_scheme, + "direct_url": direct_url, + "domain": domain, + "max_age_ms": max_age_ms, + "tags": tags, + "timeout_ms": timeout_ms, + }, + brand_styleguide_params.BrandStyleguideParams, + ), + ), + cast_to=BrandStyleguideResponse, + ) + + def web_scrape_html( + self, + *, + url: str, + actions: Optional[Iterable[brand_web_scrape_html_params.Action]] | Omit = omit, + country: Literal[ + "ad", + "ae", + "af", + "ag", + "ai", + "al", + "am", + "ao", + "ar", + "at", + "au", + "aw", + "az", + "ba", + "bb", + "bd", + "be", + "bf", + "bg", + "bh", + "bi", + "bj", + "bm", + "bn", + "bo", + "bq", + "br", + "bs", + "bw", + "by", + "bz", + "ca", + "cd", + "cf", + "cg", + "ch", + "ci", + "cl", + "cm", + "cn", + "co", + "cr", + "cv", + "cw", + "cy", + "cz", + "de", + "dj", + "dk", + "dm", + "do", + "dz", + "ec", + "ee", + "eg", + "es", + "et", + "fi", + "fj", + "fr", + "ga", + "gb", + "gd", + "ge", + "gf", + "gg", + "gh", + "gm", + "gn", + "gp", + "gq", + "gr", + "gt", + "gu", + "gw", + "gy", + "hk", + "hn", + "hr", + "ht", + "hu", + "id", + "ie", + "il", + "im", + "in", + "iq", + "ir", + "is", + "it", + "je", + "jm", + "jo", + "jp", + "ke", + "kg", + "kh", + "kn", + "kr", + "kw", + "ky", + "kz", + "la", + "lb", + "lc", + "lk", + "lr", + "ls", + "lt", + "lu", + "lv", + "ly", + "ma", + "mc", + "md", + "me", + "mf", + "mg", + "mk", + "ml", + "mm", + "mn", + "mo", + "mq", + "mr", + "mt", + "mu", + "mv", + "mw", + "mx", + "my", + "mz", + "na", + "nc", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nz", + "om", + "pa", + "pe", + "pf", + "pg", + "ph", + "pk", + "pl", + "pr", + "ps", + "pt", + "py", + "qa", + "re", + "ro", + "rs", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sr", + "ss", + "st", + "sv", + "sx", + "sy", + "sz", + "tc", + "td", + "tg", + "th", + "tj", + "tl", + "tm", + "tn", + "tr", + "tt", + "tw", + "tz", + "ua", + "ug", + "us", + "uy", + "uz", + "vc", + "ve", + "vg", + "vi", + "vn", + "ye", + "yt", + "za", + "zm", + "zw", + ] + | Omit = omit, + exclude_selectors: Optional[SequenceNotStr[str]] | Omit = omit, + headers: Dict[str, str] | Omit = omit, + include_frames: Union[bool, Literal["true", "false"]] | Omit = omit, + include_selectors: Optional[SequenceNotStr[str]] | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + pdf: brand_web_scrape_html_params.Pdf | Omit = omit, + settle_animations: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + timeout_ms: int | Omit = omit, + use_main_content_only: Union[bool, Literal["true", "false"]] | Omit = omit, + wait_for_ms: Optional[int] | Omit = omit, + zdr: Literal["enabled", "disabled"] | 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, ) -> BrandWebScrapeHTMLResponse: - """ - Scrapes the given URL and returns the raw HTML content of the page. + """Scrapes the given URL and returns the raw HTML content of the page. + + The base + request costs 1 credit; requests with browser actions cost 2 credits. Args: url: Full URL to scrape (must include http:// or https:// protocol) + actions: Optional browser actions executed in array order after the page loads and before + content is captured. Requires a paid plan. Send a JSON array in the query + parameter. Maximum: 5 actions. + + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). + + exclude_selectors: CSS selectors to remove from the result. Applied after includeSelectors. + Exclusion takes precedence: an element matching both is removed. Examples: + "nav", "footer", ".ad-banner", "[aria-hidden=true]". + + headers: Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. + + include_frames: When true, iframes are rendered inline into the returned HTML. + + include_selectors: CSS selectors. When provided, only matching subtrees (and their descendants) are + kept and everything else is dropped. When omitted, the entire document is kept. + Examples: "article.main", "#content", "[role=main]". + + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + + pdf: PDF parsing controls. Use start/end to limit text extraction and embedded-image + detection/OCR to an inclusive 1-based page range. + + settle_animations: When true, waits briefly for CSS and transition animations to settle before + extracting HTML. Defaults to false. This adds a bit of latency in exchange for + more stable output on animated pages. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). + + use_main_content_only: When true, return only the page's main content in the HTML response, excluding + headers, footers, sidebars, and navigation when detectable. + + wait_for_ms: + Optional browser wait time in milliseconds after initial page load. Min: 0. Max: + 30000 (30 seconds). + + zdr: Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -2007,7 +3200,26 @@ def web_scrape_html( extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=maybe_transform({"url": url}, brand_web_scrape_html_params.BrandWebScrapeHTMLParams), + query=maybe_transform( + { + "url": url, + "actions": actions, + "country": country, + "exclude_selectors": exclude_selectors, + "headers": headers, + "include_frames": include_frames, + "include_selectors": include_selectors, + "max_age_ms": max_age_ms, + "pdf": pdf, + "settle_animations": settle_animations, + "tags": tags, + "timeout_ms": timeout_ms, + "use_main_content_only": use_main_content_only, + "wait_for_ms": wait_for_ms, + "zdr": zdr, + }, + brand_web_scrape_html_params.BrandWebScrapeHTMLParams, + ), ), cast_to=BrandWebScrapeHTMLResponse, ) @@ -2016,74 +3228,408 @@ def web_scrape_images( self, *, url: str, + actions: Optional[Iterable[brand_web_scrape_images_params.Action]] | Omit = omit, + dedupe: Union[bool, Literal["true", "false"]] | Omit = omit, + enrichment: Optional[brand_web_scrape_images_params.Enrichment] | Omit = omit, + headers: Dict[str, str] | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + timeout_ms: int | Omit = omit, + wait_for_ms: Optional[int] | 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, + ) -> BrandWebScrapeImagesResponse: + """ + Extract image assets from a web page, including standard URLs, inline SVGs, data + URIs, responsive image sources, metadata, CSS backgrounds, video posters, and + embeds. The base request costs 1 credit, or 2 credits with browser actions. When + enrichment is enabled, the entire call costs 5 credits, including requests that + also use actions. + + Args: + url: Page URL to inspect. Must include http:// or https://. + + actions: Optional browser actions executed in array order after the page loads and before + content is captured. Requires a paid plan. Send a JSON array in the query + parameter. Maximum: 5 actions. + + dedupe: When true, visually duplicate images are removed: every image is loaded and + perceptually hashed, and only the highest-resolution copy of each duplicate + group is kept. Images that cannot be downloaded or hashed are kept. Default: + false. + + enrichment: Optional per-image processing, sent as deep-object query params such as + enrichment[resolution]=true. + + headers: Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. + + max_age_ms: Reuse a cached result this many milliseconds old or newer. Default: 86400000 (1 + day). Set to 0 to bypass cache. Maximum: 2592000000 (30 days). + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). + + wait_for_ms: Optional browser wait time in milliseconds after initial page load before + collecting images. Min: 0. Max: 30000 (30 seconds). + + 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 + """ + return self._get( + "/web/scrape/images", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "url": url, + "actions": actions, + "dedupe": dedupe, + "enrichment": enrichment, + "headers": headers, + "max_age_ms": max_age_ms, + "tags": tags, + "timeout_ms": timeout_ms, + "wait_for_ms": wait_for_ms, + }, + brand_web_scrape_images_params.BrandWebScrapeImagesParams, + ), + ), + cast_to=BrandWebScrapeImagesResponse, + ) + + def web_scrape_md( + self, + *, + url: str, + actions: Optional[Iterable[brand_web_scrape_md_params.Action]] | Omit = omit, + country: Literal[ + "ad", + "ae", + "af", + "ag", + "ai", + "al", + "am", + "ao", + "ar", + "at", + "au", + "aw", + "az", + "ba", + "bb", + "bd", + "be", + "bf", + "bg", + "bh", + "bi", + "bj", + "bm", + "bn", + "bo", + "bq", + "br", + "bs", + "bw", + "by", + "bz", + "ca", + "cd", + "cf", + "cg", + "ch", + "ci", + "cl", + "cm", + "cn", + "co", + "cr", + "cv", + "cw", + "cy", + "cz", + "de", + "dj", + "dk", + "dm", + "do", + "dz", + "ec", + "ee", + "eg", + "es", + "et", + "fi", + "fj", + "fr", + "ga", + "gb", + "gd", + "ge", + "gf", + "gg", + "gh", + "gm", + "gn", + "gp", + "gq", + "gr", + "gt", + "gu", + "gw", + "gy", + "hk", + "hn", + "hr", + "ht", + "hu", + "id", + "ie", + "il", + "im", + "in", + "iq", + "ir", + "is", + "it", + "je", + "jm", + "jo", + "jp", + "ke", + "kg", + "kh", + "kn", + "kr", + "kw", + "ky", + "kz", + "la", + "lb", + "lc", + "lk", + "lr", + "ls", + "lt", + "lu", + "lv", + "ly", + "ma", + "mc", + "md", + "me", + "mf", + "mg", + "mk", + "ml", + "mm", + "mn", + "mo", + "mq", + "mr", + "mt", + "mu", + "mv", + "mw", + "mx", + "my", + "mz", + "na", + "nc", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nz", + "om", + "pa", + "pe", + "pf", + "pg", + "ph", + "pk", + "pl", + "pr", + "ps", + "pt", + "py", + "qa", + "re", + "ro", + "rs", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sr", + "ss", + "st", + "sv", + "sx", + "sy", + "sz", + "tc", + "td", + "tg", + "th", + "tj", + "tl", + "tm", + "tn", + "tr", + "tt", + "tw", + "tz", + "ua", + "ug", + "us", + "uy", + "uz", + "vc", + "ve", + "vg", + "vi", + "vn", + "ye", + "yt", + "za", + "zm", + "zw", + ] + | Omit = omit, + exclude_selectors: Optional[SequenceNotStr[str]] | Omit = omit, + headers: Dict[str, str] | Omit = omit, + include_frames: Union[bool, Literal["true", "false"]] | Omit = omit, + include_images: Union[bool, Literal["true", "false"]] | Omit = omit, + include_links: Union[bool, Literal["true", "false"]] | Omit = omit, + include_selectors: Optional[SequenceNotStr[str]] | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + pdf: brand_web_scrape_md_params.Pdf | Omit = omit, + settle_animations: Union[bool, Literal["true", "false"]] | Omit = omit, + shorten_base64_images: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + timeout_ms: int | Omit = omit, + use_main_content_only: Union[bool, Literal["true", "false"]] | Omit = omit, + wait_for_ms: Optional[int] | Omit = omit, + zdr: Literal["enabled", "disabled"] | 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, - ) -> BrandWebScrapeImagesResponse: - """Scrapes all images from the given URL. + ) -> BrandWebScrapeMdResponse: + """Scrapes the given URL into LLM usable Markdown. - Extracts images from img, svg, - picture/source, link, and video elements including inline SVGs, base64 data - URIs, and standard URLs. + Inspect key_metadata on JSON + responses from a recognized API key; use error_code to distinguish stable + failure categories. - Args: - url: Full URL to scrape images from (must include http:// or https:// protocol) + ### Billing & errors - extra_headers: Send extra headers + | HTTP status | Billed? | Meaning | + | ----------- | ----------------------------------------- | ---------------------------------------------------------------------------------------- | + | 200 | Yes — 1 credit, or 2 credits with actions | Successful scrape, including a zero-length result when includeSelectors matched nothing | + | 400 | No | Invalid input, skipped PDF, or the page could not be scraped | + | 401 / 403 | No | Invalid/disabled key, insufficient permissions, or credits exhausted; inspect error_code | + | 404 | No | Target page returned or fingerprinted as not found | + | 408 | No | Request timed out | + | 415 | No | Unsupported content type | + | 429 | No | Per-minute rate limit exceeded; honor Retry-After | + | 500 | No | Internal error | - extra_query: Add additional query parameters to the request + Args: + url: Full URL to scrape into LLM usable Markdown (must include http:// or https:// + protocol) - extra_body: Add additional JSON properties to the request + actions: Optional browser actions executed in array order after the page loads and before + content is captured. Requires a paid plan. Send a JSON array in the query + parameter. Maximum: 5 actions. - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._get( - "/web/scrape/images", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"url": url}, brand_web_scrape_images_params.BrandWebScrapeImagesParams), - ), - cast_to=BrandWebScrapeImagesResponse, - ) + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). - def web_scrape_md( - self, - *, - url: str, - include_images: bool | Omit = omit, - include_links: bool | Omit = omit, - shorten_base64_images: bool | Omit = omit, - use_main_content_only: 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, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> BrandWebScrapeMdResponse: - """ - Scrapes the given URL, converts the HTML content to Markdown, and returns the - result. + exclude_selectors: CSS selectors to remove before conversion to Markdown. Applied after + includeSelectors. Exclusion takes precedence: an element matching both is + removed. Examples: "nav", "footer", ".ad-banner", "[aria-hidden=true]". - Args: - url: Full URL to scrape and convert to markdown (must include http:// or https:// - protocol) + headers: Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. + + include_frames: When true, the contents of iframes are rendered to Markdown. include_images: Include image references in Markdown output include_links: Preserve hyperlinks in Markdown output + include_selectors: CSS selectors. When provided, only matching HTML subtrees (and their + descendants) are kept before conversion to Markdown. When omitted, the entire + document is kept. Examples: "article.main", "#content", "[role=main]". + + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + + pdf: PDF parsing controls. Use start/end to limit text extraction and embedded-image + detection/OCR to an inclusive 1-based page range. + + settle_animations: When true, waits briefly for CSS and transition animations to settle before + converting to Markdown. Defaults to false. This adds a bit of latency in + exchange for more stable output on animated pages. + shorten_base64_images: Shorten base64-encoded image data in the Markdown output + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). + use_main_content_only: Extract only the main content of the page, excluding headers, footers, sidebars, and navigation + wait_for_ms: Optional browser wait time in milliseconds after initial page load before + converting the page to Markdown. Min: 0. Max: 30000 (30 seconds). + + zdr: Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -2102,10 +3648,23 @@ def web_scrape_md( query=maybe_transform( { "url": url, + "actions": actions, + "country": country, + "exclude_selectors": exclude_selectors, + "headers": headers, + "include_frames": include_frames, "include_images": include_images, "include_links": include_links, + "include_selectors": include_selectors, + "max_age_ms": max_age_ms, + "pdf": pdf, + "settle_animations": settle_animations, "shorten_base64_images": shorten_base64_images, + "tags": tags, + "timeout_ms": timeout_ms, "use_main_content_only": use_main_content_only, + "wait_for_ms": wait_for_ms, + "zdr": zdr, }, brand_web_scrape_md_params.BrandWebScrapeMdParams, ), @@ -2117,7 +3676,13 @@ def web_scrape_sitemap( self, *, domain: str, + headers: Dict[str, str] | Omit = omit, max_links: int | Omit = omit, + sitemap_url: str | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + timeout_ms: int | Omit = omit, + url_regex: str | Omit = omit, + zdr: Literal["enabled", "disabled"] | 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, @@ -2126,17 +3691,37 @@ def web_scrape_sitemap( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandWebScrapeSitemapResponse: """ - Crawls the sitemap of the given domain and returns all discovered page URLs. - Supports sitemap index files (recursive), parallel fetching with concurrency - control, deduplication, and filters out non-page resources (images, PDFs, etc.). + Crawl an entire website's sitemap and return all discovered page URLs. Args: - domain: Domain name to crawl sitemaps for (e.g., 'example.com'). The domain will be - automatically normalized and validated. + domain: Domain to build a sitemap for + + headers: Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. max_links: Maximum number of links to return from the sitemap crawl. Defaults to 10,000. Minimum is 1, maximum is 100,000. + sitemap_url: Optional explicit sitemap URL. When provided, exactly this sitemap is crawled + instead of discovering the domain's sitemaps. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). + + url_regex: Optional RE2-compatible regex pattern. Only URLs matching this pattern are + returned and counted against maxLinks. + + zdr: Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -2155,7 +3740,13 @@ def web_scrape_sitemap( query=maybe_transform( { "domain": domain, + "headers": headers, "max_links": max_links, + "sitemap_url": sitemap_url, + "tags": tags, + "timeout_ms": timeout_ms, + "url_regex": url_regex, + "zdr": zdr, }, brand_web_scrape_sitemap_params.BrandWebScrapeSitemapParams, ), @@ -2187,66 +3778,212 @@ def with_streaming_response(self) -> AsyncBrandResourceWithStreamingResponse: async def retrieve( self, *, - domain: str, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + domain: str | Omit = omit, + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] + ] + | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + name: str | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + ticker: str | Omit = omit, + ticker_exchange: Literal[ + "AMEX", + "AMS", + "AQS", + "ASX", + "ATH", + "BER", + "BME", + "BRU", + "BSE", + "BUD", + "BUE", + "BVC", + "CBOE", + "CNQ", + "CPH", + "DFM", + "DOH", + "DUB", + "DUS", + "DXE", + "EGX", + "FSX", + "HAM", + "HEL", + "HKSE", + "HOSE", + "ICE", + "IOB", + "IST", + "JKT", + "JNB", + "JPX", + "KLS", + "KOE", + "KSC", + "KUW", + "LIS", + "LSE", + "MCX", + "MEX", + "MIL", + "MUN", + "NASDAQ", + "NEO", + "NSE", + "NYSE", + "NZE", + "OSL", + "OTC", + "PAR", + "PNK", + "PRA", + "RIS", + "SAO", + "SAU", + "SES", + "SET", + "SGO", + "SHH", + "SHZ", + "SIX", + "STO", + "STU", + "TAI", + "TAL", + "TLV", + "TSX", + "TSXV", + "TWO", + "VIE", + "WSE", + "XETRA", ] | Omit = omit, - max_speed: bool | Omit = omit, timeout_ms: int | 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. @@ -2263,13 +4000,29 @@ async def retrieve( domain: Domain name to retrieve brand data for (e.g., 'example.com', 'google.com'). Cannot be used with name or ticker parameters. - force_language: Optional parameter to force the language of the retrieved brand data. Works with - all three lookup methods. + force_language: Language to force for the retrieved brand data. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. Works with all three lookup methods. + name: Company name to retrieve brand data for (e.g., 'Apple Inc'). Cannot be used with + domain or ticker parameters. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + ticker: Stock ticker symbol to retrieve brand data for (e.g., 'AAPL'). Cannot be used + with domain or name parameters. + + ticker_exchange: Stock exchange code. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -2293,7 +4046,12 @@ async def retrieve( { "domain": domain, "force_language": force_language, + "max_age_ms": max_age_ms, "max_speed": max_speed, + "name": name, + "tags": tags, + "ticker": ticker, + "ticker_exchange": ticker_exchange, "timeout_ms": timeout_ms, }, brand_retrieve_params.BrandRetrieveParams, @@ -2306,6 +4064,8 @@ async def ai_product( self, *, url: str, + max_age_ms: int | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -2315,15 +4075,21 @@ async def ai_product( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandAIProductResponse: """ - Beta feature: Given a single URL, determines if it is a product detail page, - classifies the platform/product type, and extracts the product information. - Supports Amazon, TikTok Shop, Etsy, and generic ecommerce sites. + Given a single URL, determines if it is a product page and extracts the product + information. Args: url: The product page URL to extract product data from. - timeout_ms: Optional timeout in milliseconds for the request. Maximum allowed value is - 300000ms (5 minutes). + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 7 days (604800000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). extra_headers: Send extra headers @@ -2338,6 +4104,8 @@ async def ai_product( body=await async_maybe_transform( { "url": url, + "max_age_ms": max_age_ms, + "tags": tags, "timeout_ms": timeout_ms, }, brand_ai_product_params.BrandAIProductParams, @@ -2353,7 +4121,9 @@ async def ai_products( self, *, domain: str, + max_age_ms: int | Omit = omit, max_products: int | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -2362,19 +4132,26 @@ async def ai_products( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandAIProductsResponse: - """Beta feature: Extract product information from a brand's website. + """Extract product information from a brand's website. - We will - analyze the website and return a list of products with details such as name, - description, image, pricing, features, and more. + We will analyze the website + and return a list of products with details such as name, description, image, + pricing, features, and more. Args: domain: The domain name to analyze. + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 7 days (604800000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + max_products: Maximum number of products to extract. - timeout_ms: Optional timeout in milliseconds for the request. Maximum allowed value is - 300000ms (5 minutes). + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). extra_headers: Send extra headers @@ -2391,7 +4168,9 @@ async def ai_products( self, *, direct_url: str, + max_age_ms: int | Omit = omit, max_products: int | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -2400,20 +4179,27 @@ async def ai_products( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandAIProductsResponse: - """Beta feature: Extract product information from a brand's website. + """Extract product information from a brand's website. - We will - analyze the website and return a list of products with details such as name, - description, image, pricing, features, and more. + We will analyze the website + and return a list of products with details such as name, description, image, + pricing, features, and more. Args: direct_url: A specific URL to use directly as the starting point for extraction without domain resolution. + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 7 days (604800000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + max_products: Maximum number of products to extract. - timeout_ms: Optional timeout in milliseconds for the request. Maximum allowed value is - 300000ms (5 minutes). + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). extra_headers: Send extra headers @@ -2430,7 +4216,9 @@ async def ai_products( self, *, domain: str | Omit = omit, + max_age_ms: int | Omit = omit, max_products: int | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | Omit = omit, direct_url: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -2445,7 +4233,9 @@ async def ai_products( body=await async_maybe_transform( { "domain": domain, + "max_age_ms": max_age_ms, "max_products": max_products, + "tags": tags, "timeout_ms": timeout_ms, "direct_url": direct_url, }, @@ -2463,6 +4253,7 @@ async def ai_query( data_to_extract: Iterable[brand_ai_query_params.DataToExtract], domain: str, specific_pages: brand_ai_query_params.SpecificPages | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -2484,6 +4275,8 @@ async def ai_query( specific_pages: Optional object specifying which pages to analyze + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -2503,6 +4296,7 @@ async def ai_query( "data_to_extract": data_to_extract, "domain": domain, "specific_pages": specific_pages, + "tags": tags, "timeout_ms": timeout_ms, }, brand_ai_query_params.BrandAIQueryParams, @@ -2516,7 +4310,10 @@ async def ai_query( async def fonts( self, *, - domain: str, + direct_url: str | Omit = omit, + domain: str | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -2526,12 +4323,26 @@ async def fonts( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandFontsResponse: """ - Extract font information from a brand's website including font families, usage + Scrape font information from a website including font families, usage statistics, fallbacks, and element/word counts. Args: + direct_url: A specific URL to fetch fonts from directly, bypassing domain resolution (e.g., + 'https://example.com/design-system'). When provided, fonts are extracted from + this exact URL. You must provide either 'domain' or 'directUrl', but not both. + domain: Domain name to extract fonts from (e.g., 'example.com', 'google.com'). The - domain will be automatically normalized and validated. + domain will be automatically normalized and validated. You must provide either + 'domain' or 'directUrl', but not both. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed @@ -2546,7 +4357,7 @@ async def fonts( timeout: Override the client-level default timeout for this request, in seconds """ return await self._get( - "/brand/fonts", + "/web/fonts", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -2554,7 +4365,10 @@ async def fonts( timeout=timeout, query=await async_maybe_transform( { + "direct_url": direct_url, "domain": domain, + "max_age_ms": max_age_ms, + "tags": tags, "timeout_ms": timeout_ms, }, brand_fonts_params.BrandFontsParams, @@ -2569,309 +4383,377 @@ async def identify_from_transaction( transaction_info: str, city: str | Omit = omit, country_gl: Literal[ - "ad", - "ae", "af", - "ag", - "ai", "al", - "am", - "an", + "dz", + "as", + "ad", "ao", + "ai", "aq", + "ag", "ar", - "as", - "at", - "au", + "am", "aw", + "au", + "at", "az", - "ba", - "bb", + "bs", + "bh", "bd", + "bb", + "by", "be", - "bf", - "bg", - "bh", - "bi", + "bz", "bj", "bm", - "bn", - "bo", - "br", - "bs", "bt", - "bv", + "bo", + "ba", "bw", - "by", - "bz", + "bv", + "br", + "io", + "bn", + "bg", + "bf", + "bi", + "kh", + "cm", "ca", - "cc", - "cd", + "cv", + "ky", "cf", - "cg", - "ch", - "ci", - "ck", + "td", "cl", - "cm", "cn", + "cx", + "cc", "co", + "km", + "cg", + "cd", + "ck", "cr", + "ci", + "hr", "cu", - "cv", - "cx", "cy", "cz", - "de", - "dj", "dk", + "dj", "dm", "do", - "dz", "ec", - "ee", "eg", - "eh", + "sv", + "gq", "er", - "es", + "ee", "et", - "fi", - "fj", "fk", - "fm", "fo", + "fj", + "fi", "fr", + "gf", + "pf", + "tf", "ga", - "gb", - "gd", + "gm", "ge", - "gf", + "de", "gh", "gi", + "gr", "gl", - "gm", - "gn", + "gd", "gp", - "gq", - "gr", - "gs", - "gt", "gu", + "gt", + "gn", "gw", "gy", - "hk", + "ht", "hm", + "va", "hn", - "hr", - "ht", + "hk", "hu", + "is", + "in", "id", + "ir", + "iq", "ie", "il", - "in", - "io", - "iq", - "ir", - "is", "it", "jm", - "jo", "jp", + "jo", + "kz", "ke", - "kg", - "kh", "ki", - "km", - "kn", "kp", "kr", "kw", - "ky", - "kz", + "kg", "la", + "lv", "lb", - "lc", - "li", - "lk", - "lr", "ls", + "lr", + "ly", + "li", "lt", "lu", - "lv", - "ly", - "ma", - "mc", - "md", - "mg", - "mh", + "mo", "mk", + "mg", + "mw", + "my", + "mv", "ml", - "mm", - "mn", - "mo", - "mp", + "mt", + "mh", "mq", "mr", - "ms", - "mt", "mu", - "mv", - "mw", + "yt", "mx", - "my", + "fm", + "md", + "mc", + "mn", + "ms", + "ma", "mz", + "mm", "na", + "nr", + "np", + "nl", + "an", "nc", + "nz", + "ni", "ne", - "nf", "ng", - "ni", - "nl", - "no", - "np", - "nr", "nu", - "nz", + "nf", + "mp", + "no", "om", + "pk", + "pw", + "ps", "pa", - "pe", - "pf", "pg", + "py", + "pe", "ph", - "pk", - "pl", - "pm", "pn", - "pr", - "ps", + "pl", "pt", - "pw", - "py", + "pr", "qa", "re", "ro", - "rs", "ru", "rw", + "sh", + "kn", + "lc", + "pm", + "vc", + "ws", + "sm", + "st", "sa", - "sb", + "sn", + "rs", "sc", - "sd", - "se", + "sl", "sg", - "sh", - "si", - "sj", "sk", - "sl", - "sm", - "sn", + "si", + "sb", "so", + "za", + "gs", + "es", + "lk", + "sd", "sr", - "st", - "sv", - "sy", + "sj", "sz", - "tc", - "td", - "tf", - "tg", - "th", + "se", + "ch", + "sy", + "tw", "tj", - "tk", + "tz", + "th", "tl", - "tm", - "tn", + "tg", + "tk", "to", - "tr", "tt", + "tn", + "tr", + "tm", + "tc", "tv", - "tw", - "tz", - "ua", "ug", - "um", + "ua", + "ae", + "gb", "us", + "um", "uy", "uz", - "va", - "vc", + "vu", "ve", + "vn", "vg", "vi", - "vn", - "vu", "wf", - "ws", + "eh", "ye", - "yt", - "za", "zm", "zw", ] | Omit = omit, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] | Omit = omit, - high_confidence_only: bool | Omit = omit, - max_speed: bool | Omit = omit, - mcc: str | Omit = omit, - phone: float | Omit = omit, + high_confidence_only: Union[bool, Literal["true", "false"]] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + mcc: Union[str, float] | Omit = omit, + phone: Union[str, float] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -2889,14 +4771,13 @@ async def identify_from_transaction( city: Optional city name to prioritize when searching for the brand. - country_gl: Optional country code (GL parameter) to specify the country. This affects the - geographic location used for search queries. + country_gl: Two-letter ISO 3166-1 alpha-2 country code (GL parameter) used to localize + search. - force_language: Optional parameter to force the language of the retrieved brand data. + force_language: Language to force for the retrieved brand data. high_confidence_only: When set to true, the API will perform an additional verification steps to ensure the identified brand matches the transaction with high confidence. - Defaults to false. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of @@ -2907,6 +4788,10 @@ async def identify_from_transaction( phone: Optional phone number from the transaction to help verify brand match. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -2936,6 +4821,7 @@ async def identify_from_transaction( "max_speed": max_speed, "mcc": mcc, "phone": phone, + "tags": tags, "timeout_ms": timeout_ms, }, brand_identify_from_transaction_params.BrandIdentifyFromTransactionParams, @@ -2948,6 +4834,7 @@ async def prefetch( self, *, domain: str, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -2958,13 +4845,13 @@ async def prefetch( ) -> BrandPrefetchResponse: """ Signal that you may fetch brand data for a particular domain soon to improve - latency. This endpoint does not charge credits and is available for paid - customers to optimize future requests. [You must be on a paid plan to use this - endpoint] + latency. Args: domain: Domain name to prefetch brand data for + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -2982,6 +4869,7 @@ async def prefetch( body=await async_maybe_transform( { "domain": domain, + "tags": tags, "timeout_ms": timeout_ms, }, brand_prefetch_params.BrandPrefetchParams, @@ -2996,6 +4884,7 @@ async def prefetch_by_email( self, *, email: str, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -3008,15 +4897,15 @@ async def prefetch_by_email( Signal that you may fetch brand data for a particular domain soon to improve latency. This endpoint accepts an email address, extracts the domain from it, validates that it's not a disposable or free email provider, and queues the - domain for prefetching. This endpoint does not charge credits and is available - for paid customers to optimize future requests. [You must be on a paid plan to - use this endpoint] + domain for prefetching. Args: email: Email address to prefetch brand data for. The domain will be extracted from the email. Free email providers (gmail.com, yahoo.com, etc.) and disposable email addresses are not allowed. + tags: Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -3034,6 +4923,7 @@ async def prefetch_by_email( body=await async_maybe_transform( { "email": email, + "tags": tags, "timeout_ms": timeout_ms, }, brand_prefetch_by_email_params.BrandPrefetchByEmailParams, @@ -3048,65 +4938,134 @@ async def retrieve_by_email( self, *, email: str, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] | Omit = omit, - max_speed: bool | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -3117,21 +5076,29 @@ async def retrieve_by_email( ) -> BrandRetrieveByEmailResponse: """ Retrieve brand information using an email address while detecting disposable and - free email addresses. This endpoint extracts the domain from the email address - and returns brand data for that domain. Disposable and free email addresses - (like gmail.com, yahoo.com) will throw a 422 error. + free email addresses. Disposable and free email addresses (like gmail.com, + yahoo.com) will throw a 422 error. Args: email: Email address to retrieve brand data for (e.g., 'contact@example.com'). The domain will be extracted from the email. Free email providers (gmail.com, yahoo.com, etc.) and disposable email addresses are not allowed. - force_language: Optional parameter to force the language of the retrieved brand data. + force_language: Language to force for the retrieved brand data. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -3155,7 +5122,9 @@ async def retrieve_by_email( { "email": email, "force_language": force_language, + "max_age_ms": max_age_ms, "max_speed": max_speed, + "tags": tags, "timeout_ms": timeout_ms, }, brand_retrieve_by_email_params.BrandRetrieveByEmailParams, @@ -3168,65 +5137,134 @@ async def retrieve_by_isin( self, *, isin: str, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] | Omit = omit, - max_speed: bool | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -3237,20 +5275,28 @@ async def retrieve_by_isin( ) -> BrandRetrieveByIsinResponse: """ Retrieve brand information using an ISIN (International Securities - Identification Number). This endpoint looks up the company associated with the - ISIN and returns its brand data. + Identification Number). Args: isin: ISIN (International Securities Identification Number) to retrieve brand data for (e.g., 'AU000000IMD5', 'US0378331005'). Must be exactly 12 characters: 2 letters followed by 9 alphanumeric characters and ending with a digit. - force_language: Optional parameter to force the language of the retrieved brand data. + force_language: Language to force for the retrieved brand data. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -3274,7 +5320,9 @@ async def retrieve_by_isin( { "isin": isin, "force_language": force_language, + "max_age_ms": max_age_ms, "max_speed": max_speed, + "tags": tags, "timeout_ms": timeout_ms, }, brand_retrieve_by_isin_params.BrandRetrieveByIsinParams, @@ -3288,306 +5336,375 @@ async def retrieve_by_name( *, name: str, country_gl: Literal[ - "ad", - "ae", "af", - "ag", - "ai", "al", - "am", - "an", + "dz", + "as", + "ad", "ao", + "ai", "aq", + "ag", "ar", - "as", - "at", - "au", + "am", "aw", + "au", + "at", "az", - "ba", - "bb", + "bs", + "bh", "bd", + "bb", + "by", "be", - "bf", - "bg", - "bh", - "bi", + "bz", "bj", "bm", - "bn", - "bo", - "br", - "bs", "bt", - "bv", + "bo", + "ba", "bw", - "by", - "bz", + "bv", + "br", + "io", + "bn", + "bg", + "bf", + "bi", + "kh", + "cm", "ca", - "cc", - "cd", + "cv", + "ky", "cf", - "cg", - "ch", - "ci", - "ck", + "td", "cl", - "cm", "cn", + "cx", + "cc", "co", + "km", + "cg", + "cd", + "ck", "cr", + "ci", + "hr", "cu", - "cv", - "cx", "cy", "cz", - "de", - "dj", "dk", + "dj", "dm", "do", - "dz", "ec", - "ee", "eg", - "eh", + "sv", + "gq", "er", - "es", + "ee", "et", - "fi", - "fj", "fk", - "fm", "fo", + "fj", + "fi", "fr", + "gf", + "pf", + "tf", "ga", - "gb", - "gd", + "gm", "ge", - "gf", + "de", "gh", "gi", + "gr", "gl", - "gm", - "gn", + "gd", "gp", - "gq", - "gr", - "gs", - "gt", "gu", + "gt", + "gn", "gw", "gy", - "hk", + "ht", "hm", + "va", "hn", - "hr", - "ht", + "hk", "hu", + "is", + "in", "id", + "ir", + "iq", "ie", "il", - "in", - "io", - "iq", - "ir", - "is", "it", "jm", - "jo", "jp", + "jo", + "kz", "ke", - "kg", - "kh", "ki", - "km", - "kn", "kp", "kr", "kw", - "ky", - "kz", + "kg", "la", + "lv", "lb", - "lc", - "li", - "lk", - "lr", "ls", + "lr", + "ly", + "li", "lt", "lu", - "lv", - "ly", - "ma", - "mc", - "md", - "mg", - "mh", + "mo", "mk", + "mg", + "mw", + "my", + "mv", "ml", - "mm", - "mn", - "mo", - "mp", + "mt", + "mh", "mq", "mr", - "ms", - "mt", "mu", - "mv", - "mw", + "yt", "mx", - "my", + "fm", + "md", + "mc", + "mn", + "ms", + "ma", "mz", + "mm", "na", + "nr", + "np", + "nl", + "an", "nc", + "nz", + "ni", "ne", - "nf", "ng", - "ni", - "nl", - "no", - "np", - "nr", "nu", - "nz", + "nf", + "mp", + "no", "om", + "pk", + "pw", + "ps", "pa", - "pe", - "pf", "pg", + "py", + "pe", "ph", - "pk", - "pl", - "pm", "pn", - "pr", - "ps", + "pl", "pt", - "pw", - "py", + "pr", "qa", "re", "ro", - "rs", "ru", "rw", + "sh", + "kn", + "lc", + "pm", + "vc", + "ws", + "sm", + "st", "sa", - "sb", + "sn", + "rs", "sc", - "sd", - "se", + "sl", "sg", - "sh", - "si", - "sj", "sk", - "sl", - "sm", - "sn", + "si", + "sb", "so", + "za", + "gs", + "es", + "lk", + "sd", "sr", - "st", - "sv", - "sy", + "sj", "sz", - "tc", - "td", - "tf", - "tg", - "th", + "se", + "ch", + "sy", + "tw", "tj", - "tk", + "tz", + "th", "tl", - "tm", - "tn", + "tg", + "tk", "to", - "tr", "tt", + "tn", + "tr", + "tm", + "tc", "tv", - "tw", - "tz", - "ua", "ug", - "um", + "ua", + "ae", + "gb", "us", + "um", "uy", "uz", - "va", - "vc", + "vu", "ve", + "vn", "vg", "vi", - "vn", - "vu", "wf", - "ws", + "eh", "ye", - "yt", - "za", "zm", "zw", ] | Omit = omit, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] | Omit = omit, - max_speed: bool | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -3596,24 +5713,31 @@ async def retrieve_by_name( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandRetrieveByNameResponse: - """Retrieve brand information using a company name. - - This endpoint searches for the - company by name and returns its brand data. + """ + Retrieve brand information using a company name. Args: name: Company name to retrieve brand data for (e.g., 'Apple Inc', 'Microsoft Corporation'). Must be 3-30 characters. - country_gl: Optional country code (GL parameter) to specify the country. This affects the - geographic location used for search queries. + country_gl: Two-letter ISO 3166-1 alpha-2 country code (GL parameter) used to localize + search. + + force_language: Language to force for the retrieved brand data. - force_language: Optional parameter to force the language of the retrieved brand data. + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -3638,7 +5762,9 @@ async def retrieve_by_name( "name": name, "country_gl": country_gl, "force_language": force_language, + "max_age_ms": max_age_ms, "max_speed": max_speed, + "tags": tags, "timeout_ms": timeout_ms, }, brand_retrieve_by_name_params.BrandRetrieveByNameParams, @@ -3651,65 +5777,134 @@ async def retrieve_by_ticker( self, *, ticker: str, - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] | Omit = omit, - max_speed: bool | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + max_speed: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, ticker_exchange: Literal[ "AMEX", "AMS", @@ -3793,22 +5988,29 @@ async def retrieve_by_ticker( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandRetrieveByTickerResponse: - """Retrieve brand information using a stock ticker symbol. - - This endpoint looks up - the company associated with the ticker and returns its brand data. + """ + Retrieve brand information using a stock ticker symbol. Args: ticker: Stock ticker symbol to retrieve brand data for (e.g., 'AAPL', 'GOOGL', 'BRK.A'). Must be 1-15 characters, letters/numbers/dots only. - force_language: Optional parameter to force the language of the retrieved brand data. + force_language: Language to force for the retrieved brand data. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. max_speed: Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. - ticker_exchange: Optional stock exchange for the ticker. Defaults to NASDAQ if not specified. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + ticker_exchange: Stock exchange code. timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed @@ -3833,7 +6035,9 @@ async def retrieve_by_ticker( { "ticker": ticker, "force_language": force_language, + "max_age_ms": max_age_ms, "max_speed": max_speed, + "tags": tags, "ticker_exchange": ticker_exchange, "timeout_ms": timeout_ms, }, @@ -3849,6 +6053,7 @@ async def retrieve_naics( input: str, max_results: int | Omit = omit, min_results: int | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -3858,18 +6063,22 @@ async def retrieve_naics( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandRetrieveNaicsResponse: """ - Endpoint to classify any brand into a 2022 NAICS code. + Classify any brand into 2022 NAICS industry codes from its domain or name. Args: - input: Brand domain or title to retrieve NAICS code for. If a valid domain is provided - in `input`, it will be used for classification, otherwise, we will search for - the brand using the provided title. + input: Brand domain or title to retrieve NAICS code for. If a valid domain is provided, + it will be used for classification, otherwise, we will search for the brand + using the provided title. max_results: Maximum number of NAICS codes to return. Must be between 1 and 10. Defaults to 5. min_results: Minimum number of NAICS codes to return. Must be at least 1. Defaults to 1. + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -3883,7 +6092,7 @@ async def retrieve_naics( timeout: Override the client-level default timeout for this request, in seconds """ return await self._get( - "/brand/naics", + "/web/naics", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -3894,6 +6103,7 @@ async def retrieve_naics( "input": input, "max_results": max_results, "min_results": min_results, + "tags": tags, "timeout_ms": timeout_ms, }, brand_retrieve_naics_params.BrandRetrieveNaicsParams, @@ -3906,6 +6116,9 @@ async def retrieve_simplified( self, *, domain: str, + max_age_ms: Optional[int] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + theme: Literal["light", "dark"] | Omit = omit, timeout_ms: int | 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. @@ -3916,12 +6129,23 @@ async def retrieve_simplified( ) -> BrandRetrieveSimplifiedResponse: """ Returns a simplified version of brand data containing only essential - information: domain, title, colors, logos, and backdrops. This endpoint is - optimized for faster responses and reduced data transfer. + information: domain, title, colors, logos, and backdrops. Optimized for faster + responses and reduced data transfer. Args: domain: Domain name to retrieve simplified brand data for + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + theme: Optional theme preference used when selecting brand assets. + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes). @@ -3944,6 +6168,9 @@ async def retrieve_simplified( query=await async_maybe_transform( { "domain": domain, + "max_age_ms": max_age_ms, + "tags": tags, + "theme": theme, "timeout_ms": timeout_ms, }, brand_retrieve_simplified_params.BrandRetrieveSimplifiedParams, @@ -3955,10 +6182,226 @@ async def retrieve_simplified( async def screenshot( self, *, - domain: str, + color_scheme: Literal["light", "dark"] | Omit = omit, + country: Literal[ + "ad", + "ae", + "af", + "ag", + "ai", + "al", + "am", + "ao", + "ar", + "at", + "au", + "aw", + "az", + "ba", + "bb", + "bd", + "be", + "bf", + "bg", + "bh", + "bi", + "bj", + "bm", + "bn", + "bo", + "bq", + "br", + "bs", + "bw", + "by", + "bz", + "ca", + "cd", + "cf", + "cg", + "ch", + "ci", + "cl", + "cm", + "cn", + "co", + "cr", + "cv", + "cw", + "cy", + "cz", + "de", + "dj", + "dk", + "dm", + "do", + "dz", + "ec", + "ee", + "eg", + "es", + "et", + "fi", + "fj", + "fr", + "ga", + "gb", + "gd", + "ge", + "gf", + "gg", + "gh", + "gm", + "gn", + "gp", + "gq", + "gr", + "gt", + "gu", + "gw", + "gy", + "hk", + "hn", + "hr", + "ht", + "hu", + "id", + "ie", + "il", + "im", + "in", + "iq", + "ir", + "is", + "it", + "je", + "jm", + "jo", + "jp", + "ke", + "kg", + "kh", + "kn", + "kr", + "kw", + "ky", + "kz", + "la", + "lb", + "lc", + "lk", + "lr", + "ls", + "lt", + "lu", + "lv", + "ly", + "ma", + "mc", + "md", + "me", + "mf", + "mg", + "mk", + "ml", + "mm", + "mn", + "mo", + "mq", + "mr", + "mt", + "mu", + "mv", + "mw", + "mx", + "my", + "mz", + "na", + "nc", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nz", + "om", + "pa", + "pe", + "pf", + "pg", + "ph", + "pk", + "pl", + "pr", + "ps", + "pt", + "py", + "qa", + "re", + "ro", + "rs", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sr", + "ss", + "st", + "sv", + "sx", + "sy", + "sz", + "tc", + "td", + "tg", + "th", + "tj", + "tl", + "tm", + "tn", + "tr", + "tt", + "tw", + "tz", + "ua", + "ug", + "us", + "uy", + "uz", + "vc", + "ve", + "vg", + "vi", + "vn", + "ye", + "yt", + "za", + "zm", + "zw", + ] + | Omit = omit, + direct_url: str | Omit = omit, + domain: str | Omit = omit, full_screenshot: Literal["true", "false"] | Omit = omit, + handle_cookie_popup: Union[bool, Literal["true", "false"]] | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, page: Literal["login", "signup", "blog", "careers", "pricing", "terms", "privacy", "contact"] | Omit = omit, - prioritize: Literal["speed", "quality"] | Omit = omit, + scroll_offset: Optional[int] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + timeout_ms: int | Omit = omit, + viewport: brand_screenshot_params.Viewport | Omit = omit, + wait_for_ms: Optional[int] | Omit = omit, + zdr: Literal["enabled", "disabled"] | 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, @@ -3966,29 +6409,67 @@ async def screenshot( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandScreenshotResponse: - """Capture a screenshot of a website. - - Supports both viewport (standard browser - view) and full-page screenshots. Can also screenshot specific page types (login, - pricing, etc.) by using heuristics to find the appropriate URL. Returns a URL to - the uploaded screenshot image hosted on our CDN. + """ + Capture a screenshot of a website. Args: + color_scheme: Optional parameter to choose the site's visual theme in the screenshot. Use + 'light' or 'dark' when the site offers both appearances. + + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). + + direct_url: A specific URL to screenshot directly, bypassing domain resolution (e.g., + 'https://example.com/pricing'). When provided, the screenshot is taken of this + exact URL. You must provide either 'domain' or 'directUrl', but not both. + domain: Domain name to take screenshot of (e.g., 'example.com', 'google.com'). The - domain will be automatically normalized and validated. + domain will be automatically normalized and validated. You must provide either + 'domain' or 'directUrl', but not both. full_screenshot: Optional parameter to determine screenshot type. If 'true', takes a full page screenshot capturing all content. If 'false' or not provided, takes a viewport screenshot (standard browser view). + handle_cookie_popup: Optional parameter to control cookie/consent popup handling. If 'true', we + dismiss cookie banner before capture. If 'false' or not provided, captures the + page without that step. + + max_age_ms: Return a cached screenshot if a prior screenshot for the same parameters exists + and is younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always capture fresh. + page: Optional parameter to specify which page type to screenshot. If provided, the system will scrape the domain's links and use heuristics to find the most appropriate URL for the specified page type (30 supported languages). If not - provided, screenshots the main domain landing page. + provided, screenshots the main domain landing page. Only applicable when using + 'domain', not 'directUrl'. + + scroll_offset: Optional vertical scroll offset in pixels for capturing a long page in + viewport-sized chunks. When provided, the full page is captured once and the + returned image is the viewport-sized slice that begins at this Y offset (e.g. + request scrollOffset=0, then 1080, then 2160 to walk a 1920x1080 landing page + top to bottom). The final slice may be shorter than the viewport height. Takes + precedence over fullScreenshot. Max: 100000. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). + + viewport: Optional browser viewport dimensions for the screenshot. Defaults to 1920x1080. - prioritize: Optional parameter to prioritize screenshot capture. If 'speed', optimizes for - faster capture with basic quality. If 'quality', optimizes for higher quality - with longer wait times. Defaults to 'quality' if not provided. + wait_for_ms: Optional browser wait time in milliseconds after initial page load before taking + the screenshot. Min: 0. Max: 30000 (30 seconds). Defaults to 3000 ms when + omitted. + + zdr: Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. extra_headers: Send extra headers @@ -3999,7 +6480,7 @@ async def screenshot( timeout: Override the client-level default timeout for this request, in seconds """ return await self._get( - "/brand/screenshot", + "/web/screenshot", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -4007,10 +6488,20 @@ async def screenshot( timeout=timeout, query=await async_maybe_transform( { + "color_scheme": color_scheme, + "country": country, + "direct_url": direct_url, "domain": domain, "full_screenshot": full_screenshot, + "handle_cookie_popup": handle_cookie_popup, + "max_age_ms": max_age_ms, "page": page, - "prioritize": prioritize, + "scroll_offset": scroll_offset, + "tags": tags, + "timeout_ms": timeout_ms, + "viewport": viewport, + "wait_for_ms": wait_for_ms, + "zdr": zdr, }, brand_screenshot_params.BrandScreenshotParams, ), @@ -4021,8 +6512,11 @@ async def screenshot( async def styleguide( self, *, + color_scheme: Literal["light", "dark"] | Omit = omit, direct_url: str | Omit = omit, domain: str | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, timeout_ms: int | 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. @@ -4032,17 +6526,30 @@ async def styleguide( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandStyleguideResponse: """ - Automatically extract comprehensive design system information from a brand's - website including colors, typography, spacing, shadows, and UI components. - Either 'domain' or 'directUrl' must be provided as a query parameter, but not - both. + Extract a comprehensive design system from a website including colors, + typography, spacing, shadows, and UI components. Args: + color_scheme: Optional browser color scheme to emulate for websites that respond to + prefers-color-scheme. This value is part of the styleguide cache key. + direct_url: A specific URL to fetch the styleguide from directly, bypassing domain - resolution (e.g., 'https://example.com/design-system'). + resolution (e.g., 'https://example.com/design-system'). When provided, the + styleguide is extracted from this exact URL. You must provide either 'domain' or + 'directUrl', but not both. domain: Domain name to extract styleguide from (e.g., 'example.com', 'google.com'). The - domain will be automatically normalized and validated. + domain will be automatically normalized and validated. You must provide either + 'domain' or 'directUrl', but not both. + + max_age_ms: Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed @@ -4057,7 +6564,7 @@ async def styleguide( timeout: Override the client-level default timeout for this request, in seconds """ return await self._get( - "/brand/styleguide", + "/web/styleguide", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -4065,8 +6572,11 @@ async def styleguide( timeout=timeout, query=await async_maybe_transform( { + "color_scheme": color_scheme, "direct_url": direct_url, "domain": domain, + "max_age_ms": max_age_ms, + "tags": tags, "timeout_ms": timeout_ms, }, brand_styleguide_params.BrandStyleguideParams, @@ -4079,6 +6589,226 @@ async def web_scrape_html( self, *, url: str, + actions: Optional[Iterable[brand_web_scrape_html_params.Action]] | Omit = omit, + country: Literal[ + "ad", + "ae", + "af", + "ag", + "ai", + "al", + "am", + "ao", + "ar", + "at", + "au", + "aw", + "az", + "ba", + "bb", + "bd", + "be", + "bf", + "bg", + "bh", + "bi", + "bj", + "bm", + "bn", + "bo", + "bq", + "br", + "bs", + "bw", + "by", + "bz", + "ca", + "cd", + "cf", + "cg", + "ch", + "ci", + "cl", + "cm", + "cn", + "co", + "cr", + "cv", + "cw", + "cy", + "cz", + "de", + "dj", + "dk", + "dm", + "do", + "dz", + "ec", + "ee", + "eg", + "es", + "et", + "fi", + "fj", + "fr", + "ga", + "gb", + "gd", + "ge", + "gf", + "gg", + "gh", + "gm", + "gn", + "gp", + "gq", + "gr", + "gt", + "gu", + "gw", + "gy", + "hk", + "hn", + "hr", + "ht", + "hu", + "id", + "ie", + "il", + "im", + "in", + "iq", + "ir", + "is", + "it", + "je", + "jm", + "jo", + "jp", + "ke", + "kg", + "kh", + "kn", + "kr", + "kw", + "ky", + "kz", + "la", + "lb", + "lc", + "lk", + "lr", + "ls", + "lt", + "lu", + "lv", + "ly", + "ma", + "mc", + "md", + "me", + "mf", + "mg", + "mk", + "ml", + "mm", + "mn", + "mo", + "mq", + "mr", + "mt", + "mu", + "mv", + "mw", + "mx", + "my", + "mz", + "na", + "nc", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nz", + "om", + "pa", + "pe", + "pf", + "pg", + "ph", + "pk", + "pl", + "pr", + "ps", + "pt", + "py", + "qa", + "re", + "ro", + "rs", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sr", + "ss", + "st", + "sv", + "sx", + "sy", + "sz", + "tc", + "td", + "tg", + "th", + "tj", + "tl", + "tm", + "tn", + "tr", + "tt", + "tw", + "tz", + "ua", + "ug", + "us", + "uy", + "uz", + "vc", + "ve", + "vg", + "vi", + "vn", + "ye", + "yt", + "za", + "zm", + "zw", + ] + | Omit = omit, + exclude_selectors: Optional[SequenceNotStr[str]] | Omit = omit, + headers: Dict[str, str] | Omit = omit, + include_frames: Union[bool, Literal["true", "false"]] | Omit = omit, + include_selectors: Optional[SequenceNotStr[str]] | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + pdf: brand_web_scrape_html_params.Pdf | Omit = omit, + settle_animations: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + timeout_ms: int | Omit = omit, + use_main_content_only: Union[bool, Literal["true", "false"]] | Omit = omit, + wait_for_ms: Optional[int] | Omit = omit, + zdr: Literal["enabled", "disabled"] | 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, @@ -4086,12 +6816,66 @@ async def web_scrape_html( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandWebScrapeHTMLResponse: - """ - Scrapes the given URL and returns the raw HTML content of the page. + """Scrapes the given URL and returns the raw HTML content of the page. + + The base + request costs 1 credit; requests with browser actions cost 2 credits. Args: url: Full URL to scrape (must include http:// or https:// protocol) + actions: Optional browser actions executed in array order after the page loads and before + content is captured. Requires a paid plan. Send a JSON array in the query + parameter. Maximum: 5 actions. + + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). + + exclude_selectors: CSS selectors to remove from the result. Applied after includeSelectors. + Exclusion takes precedence: an element matching both is removed. Examples: + "nav", "footer", ".ad-banner", "[aria-hidden=true]". + + headers: Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. + + include_frames: When true, iframes are rendered inline into the returned HTML. + + include_selectors: CSS selectors. When provided, only matching subtrees (and their descendants) are + kept and everything else is dropped. When omitted, the entire document is kept. + Examples: "article.main", "#content", "[role=main]". + + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + + pdf: PDF parsing controls. Use start/end to limit text extraction and embedded-image + detection/OCR to an inclusive 1-based page range. + + settle_animations: When true, waits briefly for CSS and transition animations to settle before + extracting HTML. Defaults to false. This adds a bit of latency in exchange for + more stable output on animated pages. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). + + use_main_content_only: When true, return only the page's main content in the HTML response, excluding + headers, footers, sidebars, and navigation when detectable. + + wait_for_ms: + Optional browser wait time in milliseconds after initial page load. Min: 0. Max: + 30000 (30 seconds). + + zdr: Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -4107,7 +6891,26 @@ async def web_scrape_html( extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=await async_maybe_transform({"url": url}, brand_web_scrape_html_params.BrandWebScrapeHTMLParams), + query=await async_maybe_transform( + { + "url": url, + "actions": actions, + "country": country, + "exclude_selectors": exclude_selectors, + "headers": headers, + "include_frames": include_frames, + "include_selectors": include_selectors, + "max_age_ms": max_age_ms, + "pdf": pdf, + "settle_animations": settle_animations, + "tags": tags, + "timeout_ms": timeout_ms, + "use_main_content_only": use_main_content_only, + "wait_for_ms": wait_for_ms, + "zdr": zdr, + }, + brand_web_scrape_html_params.BrandWebScrapeHTMLParams, + ), ), cast_to=BrandWebScrapeHTMLResponse, ) @@ -4116,6 +6919,14 @@ async def web_scrape_images( self, *, url: str, + actions: Optional[Iterable[brand_web_scrape_images_params.Action]] | Omit = omit, + dedupe: Union[bool, Literal["true", "false"]] | Omit = omit, + enrichment: Optional[brand_web_scrape_images_params.Enrichment] | Omit = omit, + headers: Dict[str, str] | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + timeout_ms: int | Omit = omit, + wait_for_ms: Optional[int] | 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, @@ -4123,14 +6934,45 @@ async def web_scrape_images( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandWebScrapeImagesResponse: - """Scrapes all images from the given URL. - - Extracts images from img, svg, - picture/source, link, and video elements including inline SVGs, base64 data - URIs, and standard URLs. + """ + Extract image assets from a web page, including standard URLs, inline SVGs, data + URIs, responsive image sources, metadata, CSS backgrounds, video posters, and + embeds. The base request costs 1 credit, or 2 credits with browser actions. When + enrichment is enabled, the entire call costs 5 credits, including requests that + also use actions. Args: - url: Full URL to scrape images from (must include http:// or https:// protocol) + url: Page URL to inspect. Must include http:// or https://. + + actions: Optional browser actions executed in array order after the page loads and before + content is captured. Requires a paid plan. Send a JSON array in the query + parameter. Maximum: 5 actions. + + dedupe: When true, visually duplicate images are removed: every image is loaded and + perceptually hashed, and only the highest-resolution copy of each duplicate + group is kept. Images that cannot be downloaded or hashed are kept. Default: + false. + + enrichment: Optional per-image processing, sent as deep-object query params such as + enrichment[resolution]=true. + + headers: Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. + + max_age_ms: Reuse a cached result this many milliseconds old or newer. Default: 86400000 (1 + day). Set to 0 to bypass cache. Maximum: 2592000000 (30 days). + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). + + wait_for_ms: Optional browser wait time in milliseconds after initial page load before + collecting images. Min: 0. Max: 30000 (30 seconds). extra_headers: Send extra headers @@ -4148,7 +6990,18 @@ async def web_scrape_images( extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( - {"url": url}, brand_web_scrape_images_params.BrandWebScrapeImagesParams + { + "url": url, + "actions": actions, + "dedupe": dedupe, + "enrichment": enrichment, + "headers": headers, + "max_age_ms": max_age_ms, + "tags": tags, + "timeout_ms": timeout_ms, + "wait_for_ms": wait_for_ms, + }, + brand_web_scrape_images_params.BrandWebScrapeImagesParams, ), ), cast_to=BrandWebScrapeImagesResponse, @@ -4158,10 +7011,229 @@ async def web_scrape_md( self, *, url: str, - include_images: bool | Omit = omit, - include_links: bool | Omit = omit, - shorten_base64_images: bool | Omit = omit, - use_main_content_only: bool | Omit = omit, + actions: Optional[Iterable[brand_web_scrape_md_params.Action]] | Omit = omit, + country: Literal[ + "ad", + "ae", + "af", + "ag", + "ai", + "al", + "am", + "ao", + "ar", + "at", + "au", + "aw", + "az", + "ba", + "bb", + "bd", + "be", + "bf", + "bg", + "bh", + "bi", + "bj", + "bm", + "bn", + "bo", + "bq", + "br", + "bs", + "bw", + "by", + "bz", + "ca", + "cd", + "cf", + "cg", + "ch", + "ci", + "cl", + "cm", + "cn", + "co", + "cr", + "cv", + "cw", + "cy", + "cz", + "de", + "dj", + "dk", + "dm", + "do", + "dz", + "ec", + "ee", + "eg", + "es", + "et", + "fi", + "fj", + "fr", + "ga", + "gb", + "gd", + "ge", + "gf", + "gg", + "gh", + "gm", + "gn", + "gp", + "gq", + "gr", + "gt", + "gu", + "gw", + "gy", + "hk", + "hn", + "hr", + "ht", + "hu", + "id", + "ie", + "il", + "im", + "in", + "iq", + "ir", + "is", + "it", + "je", + "jm", + "jo", + "jp", + "ke", + "kg", + "kh", + "kn", + "kr", + "kw", + "ky", + "kz", + "la", + "lb", + "lc", + "lk", + "lr", + "ls", + "lt", + "lu", + "lv", + "ly", + "ma", + "mc", + "md", + "me", + "mf", + "mg", + "mk", + "ml", + "mm", + "mn", + "mo", + "mq", + "mr", + "mt", + "mu", + "mv", + "mw", + "mx", + "my", + "mz", + "na", + "nc", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nz", + "om", + "pa", + "pe", + "pf", + "pg", + "ph", + "pk", + "pl", + "pr", + "ps", + "pt", + "py", + "qa", + "re", + "ro", + "rs", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sr", + "ss", + "st", + "sv", + "sx", + "sy", + "sz", + "tc", + "td", + "tg", + "th", + "tj", + "tl", + "tm", + "tn", + "tr", + "tt", + "tw", + "tz", + "ua", + "ug", + "us", + "uy", + "uz", + "vc", + "ve", + "vg", + "vi", + "vn", + "ye", + "yt", + "za", + "zm", + "zw", + ] + | Omit = omit, + exclude_selectors: Optional[SequenceNotStr[str]] | Omit = omit, + headers: Dict[str, str] | Omit = omit, + include_frames: Union[bool, Literal["true", "false"]] | Omit = omit, + include_images: Union[bool, Literal["true", "false"]] | Omit = omit, + include_links: Union[bool, Literal["true", "false"]] | Omit = omit, + include_selectors: Optional[SequenceNotStr[str]] | Omit = omit, + max_age_ms: Optional[int] | Omit = omit, + pdf: brand_web_scrape_md_params.Pdf | Omit = omit, + settle_animations: Union[bool, Literal["true", "false"]] | Omit = omit, + shorten_base64_images: Union[bool, Literal["true", "false"]] | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + timeout_ms: int | Omit = omit, + use_main_content_only: Union[bool, Literal["true", "false"]] | Omit = omit, + wait_for_ms: Optional[int] | Omit = omit, + zdr: Literal["enabled", "disabled"] | 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, @@ -4169,23 +7241,86 @@ async def web_scrape_md( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandWebScrapeMdResponse: - """ - Scrapes the given URL, converts the HTML content to Markdown, and returns the - result. + """Scrapes the given URL into LLM usable Markdown. + + Inspect key_metadata on JSON + responses from a recognized API key; use error_code to distinguish stable + failure categories. + + ### Billing & errors + + | HTTP status | Billed? | Meaning | + | ----------- | ----------------------------------------- | ---------------------------------------------------------------------------------------- | + | 200 | Yes — 1 credit, or 2 credits with actions | Successful scrape, including a zero-length result when includeSelectors matched nothing | + | 400 | No | Invalid input, skipped PDF, or the page could not be scraped | + | 401 / 403 | No | Invalid/disabled key, insufficient permissions, or credits exhausted; inspect error_code | + | 404 | No | Target page returned or fingerprinted as not found | + | 408 | No | Request timed out | + | 415 | No | Unsupported content type | + | 429 | No | Per-minute rate limit exceeded; honor Retry-After | + | 500 | No | Internal error | Args: - url: Full URL to scrape and convert to markdown (must include http:// or https:// + url: Full URL to scrape into LLM usable Markdown (must include http:// or https:// protocol) + actions: Optional browser actions executed in array order after the page loads and before + content is captured. Requires a paid plan. Send a JSON array in the query + parameter. Maximum: 5 actions. + + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). + + exclude_selectors: CSS selectors to remove before conversion to Markdown. Applied after + includeSelectors. Exclusion takes precedence: an element matching both is + removed. Examples: "nav", "footer", ".ad-banner", "[aria-hidden=true]". + + headers: Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. + + include_frames: When true, the contents of iframes are rendered to Markdown. + include_images: Include image references in Markdown output include_links: Preserve hyperlinks in Markdown output + include_selectors: CSS selectors. When provided, only matching HTML subtrees (and their + descendants) are kept before conversion to Markdown. When omitted, the entire + document is kept. Examples: "article.main", "#content", "[role=main]". + + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + + pdf: PDF parsing controls. Use start/end to limit text extraction and embedded-image + detection/OCR to an inclusive 1-based page range. + + settle_animations: When true, waits briefly for CSS and transition animations to settle before + converting to Markdown. Defaults to false. This adds a bit of latency in + exchange for more stable output on animated pages. + shorten_base64_images: Shorten base64-encoded image data in the Markdown output + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). + use_main_content_only: Extract only the main content of the page, excluding headers, footers, sidebars, and navigation + wait_for_ms: Optional browser wait time in milliseconds after initial page load before + converting the page to Markdown. Min: 0. Max: 30000 (30 seconds). + + zdr: Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -4204,10 +7339,23 @@ async def web_scrape_md( query=await async_maybe_transform( { "url": url, + "actions": actions, + "country": country, + "exclude_selectors": exclude_selectors, + "headers": headers, + "include_frames": include_frames, "include_images": include_images, "include_links": include_links, + "include_selectors": include_selectors, + "max_age_ms": max_age_ms, + "pdf": pdf, + "settle_animations": settle_animations, "shorten_base64_images": shorten_base64_images, + "tags": tags, + "timeout_ms": timeout_ms, "use_main_content_only": use_main_content_only, + "wait_for_ms": wait_for_ms, + "zdr": zdr, }, brand_web_scrape_md_params.BrandWebScrapeMdParams, ), @@ -4219,7 +7367,13 @@ async def web_scrape_sitemap( self, *, domain: str, + headers: Dict[str, str] | Omit = omit, max_links: int | Omit = omit, + sitemap_url: str | Omit = omit, + tags: SequenceNotStr[str] | Omit = omit, + timeout_ms: int | Omit = omit, + url_regex: str | Omit = omit, + zdr: Literal["enabled", "disabled"] | 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, @@ -4228,17 +7382,37 @@ async def web_scrape_sitemap( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BrandWebScrapeSitemapResponse: """ - Crawls the sitemap of the given domain and returns all discovered page URLs. - Supports sitemap index files (recursive), parallel fetching with concurrency - control, deduplication, and filters out non-page resources (images, PDFs, etc.). + Crawl an entire website's sitemap and return all discovered page URLs. Args: - domain: Domain name to crawl sitemaps for (e.g., 'example.com'). The domain will be - automatically normalized and validated. + domain: Domain to build a sitemap for + + headers: Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. max_links: Maximum number of links to return from the sitemap crawl. Defaults to 10,000. Minimum is 1, maximum is 100,000. + sitemap_url: Optional explicit sitemap URL. When provided, exactly this sitemap is crawled + instead of discovering the domain's sitemaps. + + tags: Optional comma-separated caller-defined tags for tracking this request. Tags are + recorded on the request's usage log and can be used to filter usage on the + dashboard usage page. Up to 20 tags, each 1-50 characters. + + timeout_ms: Optional timeout in milliseconds for the request. If the request takes longer + than this value, it will be aborted with a 408 status code. Maximum allowed + value is 300000ms (5 minutes). + + url_regex: Optional RE2-compatible regex pattern. Only URLs matching this pattern are + returned and counted against maxLinks. + + zdr: Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -4257,7 +7431,13 @@ async def web_scrape_sitemap( query=await async_maybe_transform( { "domain": domain, + "headers": headers, "max_links": max_links, + "sitemap_url": sitemap_url, + "tags": tags, + "timeout_ms": timeout_ms, + "url_regex": url_regex, + "zdr": zdr, }, brand_web_scrape_sitemap_params.BrandWebScrapeSitemapParams, ), diff --git a/src/brand/dev/types/brand_ai_product_params.py b/src/brand/dev/types/brand_ai_product_params.py index 17e62c90..9ed7fd7c 100644 --- a/src/brand/dev/types/brand_ai_product_params.py +++ b/src/brand/dev/types/brand_ai_product_params.py @@ -4,6 +4,7 @@ from typing_extensions import Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandAIProductParams"] @@ -13,8 +14,19 @@ class BrandAIProductParams(TypedDict, total=False): url: Required[str] """The product page URL to extract product data from.""" + max_age_ms: Annotated[int, PropertyInfo(alias="maxAgeMs")] + """ + Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 7 days (604800000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + """ + + tags: SequenceNotStr[str] + """Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters.""" + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. - Maximum allowed value is 300000ms (5 minutes). + If the request takes longer than this value, it will be aborted with a 408 + status code. Maximum allowed value is 300000ms (5 minutes). """ diff --git a/src/brand/dev/types/brand_ai_product_response.py b/src/brand/dev/types/brand_ai_product_response.py index eb31de27..e9f04328 100644 --- a/src/brand/dev/types/brand_ai_product_response.py +++ b/src/brand/dev/types/brand_ai_product_response.py @@ -5,7 +5,20 @@ from .._models import BaseModel -__all__ = ["BrandAIProductResponse", "Product"] +__all__ = ["BrandAIProductResponse", "KeyMetadata", "Product"] + + +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" class Product(BaseModel): @@ -23,6 +36,9 @@ class Product(BaseModel): name: str """Name of the product""" + sku: Optional[str] = None + """Stock Keeping Unit (product identifier). Null if no identifier is found.""" + tags: List[str] """Tags associated with the product""" @@ -55,6 +71,13 @@ class BrandAIProductResponse(BaseModel): is_product_page: Optional[bool] = None """Whether the given URL is a product detail page""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + platform: Optional[Literal["amazon", "tiktok_shop", "etsy", "generic"]] = None """The detected ecommerce platform, or null if not a product page""" diff --git a/src/brand/dev/types/brand_ai_products_params.py b/src/brand/dev/types/brand_ai_products_params.py index 9a61efee..9651c162 100644 --- a/src/brand/dev/types/brand_ai_products_params.py +++ b/src/brand/dev/types/brand_ai_products_params.py @@ -5,6 +5,7 @@ from typing import Union from typing_extensions import Required, Annotated, TypeAlias, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandAIProductsParams", "ByDomain", "ByDirectURL"] @@ -14,13 +15,24 @@ class ByDomain(TypedDict, total=False): domain: Required[str] """The domain name to analyze.""" + max_age_ms: Annotated[int, PropertyInfo(alias="maxAgeMs")] + """ + Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 7 days (604800000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + """ + max_products: Annotated[int, PropertyInfo(alias="maxProducts")] """Maximum number of products to extract.""" + tags: SequenceNotStr[str] + """Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters.""" + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. - Maximum allowed value is 300000ms (5 minutes). + If the request takes longer than this value, it will be aborted with a 408 + status code. Maximum allowed value is 300000ms (5 minutes). """ @@ -31,13 +43,24 @@ class ByDirectURL(TypedDict, total=False): domain resolution. """ + max_age_ms: Annotated[int, PropertyInfo(alias="maxAgeMs")] + """ + Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 7 days (604800000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + """ + max_products: Annotated[int, PropertyInfo(alias="maxProducts")] """Maximum number of products to extract.""" + tags: SequenceNotStr[str] + """Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters.""" + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. - Maximum allowed value is 300000ms (5 minutes). + If the request takes longer than this value, it will be aborted with a 408 + status code. Maximum allowed value is 300000ms (5 minutes). """ diff --git a/src/brand/dev/types/brand_ai_products_response.py b/src/brand/dev/types/brand_ai_products_response.py index 4100a1a9..eee1953a 100644 --- a/src/brand/dev/types/brand_ai_products_response.py +++ b/src/brand/dev/types/brand_ai_products_response.py @@ -5,7 +5,20 @@ from .._models import BaseModel -__all__ = ["BrandAIProductsResponse", "Product"] +__all__ = ["BrandAIProductsResponse", "KeyMetadata", "Product"] + + +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" class Product(BaseModel): @@ -21,6 +34,9 @@ class Product(BaseModel): name: str """Name of the product""" + sku: Optional[str] = None + """Stock Keeping Unit (product identifier). Null if no identifier is found.""" + tags: List[str] """Tags associated with the product""" @@ -50,5 +66,12 @@ class Product(BaseModel): class BrandAIProductsResponse(BaseModel): + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + products: Optional[List[Product]] = None """Array of products extracted from the website""" diff --git a/src/brand/dev/types/brand_ai_query_params.py b/src/brand/dev/types/brand_ai_query_params.py index d45a8218..d0c76888 100644 --- a/src/brand/dev/types/brand_ai_query_params.py +++ b/src/brand/dev/types/brand_ai_query_params.py @@ -5,6 +5,7 @@ from typing import Dict, Iterable from typing_extensions import Literal, Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandAIQueryParams", "DataToExtract", "SpecificPages"] @@ -20,6 +21,9 @@ class BrandAIQueryParams(TypedDict, total=False): specific_pages: SpecificPages """Optional object specifying which pages to analyze""" + tags: SequenceNotStr[str] + """Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters.""" + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. diff --git a/src/brand/dev/types/brand_ai_query_response.py b/src/brand/dev/types/brand_ai_query_response.py index 99714586..487c2191 100644 --- a/src/brand/dev/types/brand_ai_query_response.py +++ b/src/brand/dev/types/brand_ai_query_response.py @@ -4,7 +4,7 @@ from .._models import BaseModel -__all__ = ["BrandAIQueryResponse", "DataExtracted"] +__all__ = ["BrandAIQueryResponse", "DataExtracted", "KeyMetadata"] class DataExtracted(BaseModel): @@ -19,6 +19,19 @@ class DataExtracted(BaseModel): """ +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class BrandAIQueryResponse(BaseModel): data_extracted: Optional[List[DataExtracted]] = None """Array of extracted data points""" @@ -26,6 +39,13 @@ class BrandAIQueryResponse(BaseModel): domain: Optional[str] = None """The domain that was analyzed""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + status: Optional[str] = None """Status of the response, e.g., 'ok'""" diff --git a/src/brand/dev/types/brand_fonts_params.py b/src/brand/dev/types/brand_fonts_params.py index db13d2f5..1d7ba7ca 100644 --- a/src/brand/dev/types/brand_fonts_params.py +++ b/src/brand/dev/types/brand_fonts_params.py @@ -2,18 +2,43 @@ from __future__ import annotations -from typing_extensions import Required, Annotated, TypedDict +from typing import Optional +from typing_extensions import Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandFontsParams"] class BrandFontsParams(TypedDict, total=False): - domain: Required[str] + direct_url: Annotated[str, PropertyInfo(alias="directUrl")] + """ + A specific URL to fetch fonts from directly, bypassing domain resolution (e.g., + 'https://example.com/design-system'). When provided, fonts are extracted from + this exact URL. You must provide either 'domain' or 'directUrl', but not both. + """ + + domain: str """Domain name to extract fonts from (e.g., 'example.com', 'google.com'). - The domain will be automatically normalized and validated. + The domain will be automatically normalized and validated. You must provide + either 'domain' or 'directUrl', but not both. + """ + + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """ + Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + """ + + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. """ timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] diff --git a/src/brand/dev/types/brand_fonts_response.py b/src/brand/dev/types/brand_fonts_response.py index 2721af9c..cb0df8c6 100644 --- a/src/brand/dev/types/brand_fonts_response.py +++ b/src/brand/dev/types/brand_fonts_response.py @@ -1,10 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List +from typing import Dict, List, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo from .._models import BaseModel -__all__ = ["BrandFontsResponse", "Font"] +__all__ = ["BrandFontsResponse", "Font", "FontLinks", "KeyMetadata"] class Font(BaseModel): @@ -30,6 +33,43 @@ class Font(BaseModel): """Array of CSS selectors or element types where this font is used""" +class FontLinks(BaseModel): + files: Dict[str, str] + """Upright font files keyed by weight string (e.g. + + "400" for regular, "500", "700"). Values are absolute URLs. + """ + + type: Literal["google", "custom"] + + category: Optional[str] = None + """Google Fonts category when type is google (e.g. + + sans-serif, serif, monospace, display, handwriting). Omitted for custom fonts + when unknown. + """ + + display_name: Optional[str] = FieldInfo(alias="displayName", default=None) + """ + Present when type is custom: human-readable name derived from the fontLinks key + (strip build/hash suffixes, split camelCase / PascalCase, normalize separators). + Google entries omit this. + """ + + +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class BrandFontsResponse(BaseModel): code: int """HTTP status code, e.g., 200""" @@ -42,3 +82,17 @@ class BrandFontsResponse(BaseModel): status: str """Status of the response, e.g., 'ok'""" + + font_links: Optional[Dict[str, FontLinks]] = FieldInfo(alias="fontLinks", default=None) + """ + Font assets keyed by family name as it appears in the fonts array (non-generic + names only). Clients match entries in fonts to pick a file URL from files. + Omitted when no families resolve to Google or custom @font-face URLs. + """ + + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ diff --git a/src/brand/dev/types/brand_identify_from_transaction_params.py b/src/brand/dev/types/brand_identify_from_transaction_params.py index e04b1e53..d6b472af 100644 --- a/src/brand/dev/types/brand_identify_from_transaction_params.py +++ b/src/brand/dev/types/brand_identify_from_transaction_params.py @@ -2,8 +2,10 @@ from __future__ import annotations +from typing import Union, Optional from typing_extensions import Literal, Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandIdentifyFromTransactionParams"] @@ -17,333 +19,406 @@ class BrandIdentifyFromTransactionParams(TypedDict, total=False): """Optional city name to prioritize when searching for the brand.""" country_gl: Literal[ - "ad", - "ae", "af", - "ag", - "ai", "al", - "am", - "an", + "dz", + "as", + "ad", "ao", + "ai", "aq", + "ag", "ar", - "as", - "at", - "au", + "am", "aw", + "au", + "at", "az", - "ba", - "bb", + "bs", + "bh", "bd", + "bb", + "by", "be", - "bf", - "bg", - "bh", - "bi", + "bz", "bj", "bm", - "bn", - "bo", - "br", - "bs", "bt", - "bv", + "bo", + "ba", "bw", - "by", - "bz", + "bv", + "br", + "io", + "bn", + "bg", + "bf", + "bi", + "kh", + "cm", "ca", - "cc", - "cd", + "cv", + "ky", "cf", - "cg", - "ch", - "ci", - "ck", + "td", "cl", - "cm", "cn", + "cx", + "cc", "co", + "km", + "cg", + "cd", + "ck", "cr", + "ci", + "hr", "cu", - "cv", - "cx", "cy", "cz", - "de", - "dj", "dk", + "dj", "dm", "do", - "dz", "ec", - "ee", "eg", - "eh", + "sv", + "gq", "er", - "es", + "ee", "et", - "fi", - "fj", "fk", - "fm", "fo", + "fj", + "fi", "fr", + "gf", + "pf", + "tf", "ga", - "gb", - "gd", + "gm", "ge", - "gf", + "de", "gh", "gi", + "gr", "gl", - "gm", - "gn", + "gd", "gp", - "gq", - "gr", - "gs", - "gt", "gu", + "gt", + "gn", "gw", "gy", - "hk", + "ht", "hm", + "va", "hn", - "hr", - "ht", + "hk", "hu", + "is", + "in", "id", + "ir", + "iq", "ie", "il", - "in", - "io", - "iq", - "ir", - "is", "it", "jm", - "jo", "jp", + "jo", + "kz", "ke", - "kg", - "kh", "ki", - "km", - "kn", "kp", "kr", "kw", - "ky", - "kz", + "kg", "la", + "lv", "lb", - "lc", - "li", - "lk", - "lr", "ls", + "lr", + "ly", + "li", "lt", "lu", - "lv", - "ly", - "ma", - "mc", - "md", - "mg", - "mh", + "mo", "mk", + "mg", + "mw", + "my", + "mv", "ml", - "mm", - "mn", - "mo", - "mp", + "mt", + "mh", "mq", "mr", - "ms", - "mt", "mu", - "mv", - "mw", + "yt", "mx", - "my", + "fm", + "md", + "mc", + "mn", + "ms", + "ma", "mz", + "mm", "na", + "nr", + "np", + "nl", + "an", "nc", + "nz", + "ni", "ne", - "nf", "ng", - "ni", - "nl", - "no", - "np", - "nr", "nu", - "nz", + "nf", + "mp", + "no", "om", + "pk", + "pw", + "ps", "pa", - "pe", - "pf", "pg", + "py", + "pe", "ph", - "pk", - "pl", - "pm", "pn", - "pr", - "ps", + "pl", "pt", - "pw", - "py", + "pr", "qa", "re", "ro", - "rs", "ru", "rw", + "sh", + "kn", + "lc", + "pm", + "vc", + "ws", + "sm", + "st", "sa", - "sb", + "sn", + "rs", "sc", - "sd", - "se", + "sl", "sg", - "sh", - "si", - "sj", "sk", - "sl", - "sm", - "sn", + "si", + "sb", "so", + "za", + "gs", + "es", + "lk", + "sd", "sr", - "st", - "sv", - "sy", + "sj", "sz", - "tc", - "td", - "tf", - "tg", - "th", + "se", + "ch", + "sy", + "tw", "tj", - "tk", + "tz", + "th", "tl", - "tm", - "tn", + "tg", + "tk", "to", - "tr", "tt", + "tn", + "tr", + "tm", + "tc", "tv", - "tw", - "tz", - "ua", "ug", - "um", + "ua", + "ae", + "gb", "us", + "um", "uy", "uz", - "va", - "vc", + "vu", "ve", + "vn", "vg", "vi", - "vn", - "vu", "wf", - "ws", + "eh", "ye", - "yt", - "za", "zm", "zw", ] - """Optional country code (GL parameter) to specify the country. - - This affects the geographic location used for search queries. + """ + Two-letter ISO 3166-1 alpha-2 country code (GL parameter) used to localize + search. """ - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] - """Optional parameter to force the language of the retrieved brand data.""" + """Language to force for the retrieved brand data.""" - high_confidence_only: bool + high_confidence_only: Union[bool, Literal["true", "false"]] """ When set to true, the API will perform an additional verification steps to ensure the identified brand matches the transaction with high confidence. - Defaults to false. """ - max_speed: Annotated[bool, PropertyInfo(alias="maxSpeed")] + max_speed: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="maxSpeed")] """Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. """ - mcc: str + mcc: Union[str, float] """ Optional Merchant Category Code (MCC) to help identify the business category/industry. """ - phone: float + phone: Union[str, float] """Optional phone number from the transaction to help verify brand match.""" + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. diff --git a/src/brand/dev/types/brand_identify_from_transaction_response.py b/src/brand/dev/types/brand_identify_from_transaction_response.py index 5c1261dd..a0c74aca 100644 --- a/src/brand/dev/types/brand_identify_from_transaction_response.py +++ b/src/brand/dev/types/brand_identify_from_transaction_response.py @@ -21,6 +21,7 @@ "BrandLogoResolution", "BrandSocial", "BrandStock", + "KeyMetadata", ] @@ -169,7 +170,6 @@ class BrandIndustriesEic(BaseModel): "Streaming Platforms (Video, Music, Audio)", "Gaming & Interactive Entertainment", "Creator Economy & Influencer Platforms", - "Advertising, Adtech & Media Buying", "Film, TV & Production Studios", "Events, Venues & Live Entertainment", "Virtual Worlds & Metaverse Experiences", @@ -230,6 +230,7 @@ class BrandIndustriesEic(BaseModel): "Streetwear & Emerging Luxury", "Couture & Made-to-Measure", "News Publishing & Journalism", + "Advertising, Adtech & Media Buying", "Digital Media & Content Platforms", "Broadcasting (TV & Radio)", "Podcasting & Audio Media", @@ -415,8 +416,42 @@ class BrandLogo(BaseModel): class BrandSocial(BaseModel): - type: Optional[str] = None - """Type of social media, e.g., 'facebook', 'twitter'""" + type: Optional[ + Literal[ + "x", + "facebook", + "instagram", + "linkedin", + "youtube", + "pinterest", + "tiktok", + "dribbble", + "github", + "behance", + "snapchat", + "whatsapp", + "telegram", + "line", + "discord", + "twitch", + "vimeo", + "imdb", + "tumblr", + "flickr", + "giphy", + "medium", + "spotify", + "soundcloud", + "tripadvisor", + "yelp", + "producthunt", + "reddit", + "crunchbase", + "appstore", + "playstore", + ] + ] = None + """Type of social media platform""" url: Optional[str] = None """URL of the social media page""" @@ -470,6 +505,132 @@ class Brand(BaseModel): phone: Optional[str] = None """Company phone number""" + primary_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] + ] = None + """Language to force for the retrieved brand data.""" + slogan: Optional[str] = None """The brand's slogan""" @@ -486,6 +647,19 @@ class Brand(BaseModel): """The title or name of the brand""" +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class BrandIdentifyFromTransactionResponse(BaseModel): brand: Optional[Brand] = None """Detailed brand information""" @@ -493,5 +667,12 @@ class BrandIdentifyFromTransactionResponse(BaseModel): code: Optional[int] = None """HTTP status code""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + status: Optional[str] = None """Status of the response, e.g., 'ok'""" diff --git a/src/brand/dev/types/brand_prefetch_by_email_params.py b/src/brand/dev/types/brand_prefetch_by_email_params.py index ec7cc6ff..777ed756 100644 --- a/src/brand/dev/types/brand_prefetch_by_email_params.py +++ b/src/brand/dev/types/brand_prefetch_by_email_params.py @@ -4,6 +4,7 @@ from typing_extensions import Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandPrefetchByEmailParams"] @@ -17,6 +18,9 @@ class BrandPrefetchByEmailParams(TypedDict, total=False): yahoo.com, etc.) and disposable email addresses are not allowed. """ + tags: SequenceNotStr[str] + """Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters.""" + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. diff --git a/src/brand/dev/types/brand_prefetch_by_email_response.py b/src/brand/dev/types/brand_prefetch_by_email_response.py index c117f7d5..47e94547 100644 --- a/src/brand/dev/types/brand_prefetch_by_email_response.py +++ b/src/brand/dev/types/brand_prefetch_by_email_response.py @@ -4,13 +4,33 @@ from .._models import BaseModel -__all__ = ["BrandPrefetchByEmailResponse"] +__all__ = ["BrandPrefetchByEmailResponse", "KeyMetadata"] + + +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" class BrandPrefetchByEmailResponse(BaseModel): domain: Optional[str] = None """The domain that was queued for prefetching""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + message: Optional[str] = None """Success message""" diff --git a/src/brand/dev/types/brand_prefetch_params.py b/src/brand/dev/types/brand_prefetch_params.py index 02c13f67..8e605a0f 100644 --- a/src/brand/dev/types/brand_prefetch_params.py +++ b/src/brand/dev/types/brand_prefetch_params.py @@ -4,6 +4,7 @@ from typing_extensions import Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandPrefetchParams"] @@ -13,6 +14,9 @@ class BrandPrefetchParams(TypedDict, total=False): domain: Required[str] """Domain name to prefetch brand data for""" + tags: SequenceNotStr[str] + """Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters.""" + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. diff --git a/src/brand/dev/types/brand_prefetch_response.py b/src/brand/dev/types/brand_prefetch_response.py index 4995856a..de091a9e 100644 --- a/src/brand/dev/types/brand_prefetch_response.py +++ b/src/brand/dev/types/brand_prefetch_response.py @@ -4,13 +4,33 @@ from .._models import BaseModel -__all__ = ["BrandPrefetchResponse"] +__all__ = ["BrandPrefetchResponse", "KeyMetadata"] + + +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" class BrandPrefetchResponse(BaseModel): domain: Optional[str] = None """The domain that was queued for prefetching""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + message: Optional[str] = None """Success message""" diff --git a/src/brand/dev/types/brand_retrieve_by_email_params.py b/src/brand/dev/types/brand_retrieve_by_email_params.py index 886c2135..bcfc6267 100644 --- a/src/brand/dev/types/brand_retrieve_by_email_params.py +++ b/src/brand/dev/types/brand_retrieve_by_email_params.py @@ -2,8 +2,10 @@ from __future__ import annotations +from typing import Union, Optional from typing_extensions import Literal, Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandRetrieveByEmailParams"] @@ -17,72 +19,154 @@ class BrandRetrieveByEmailParams(TypedDict, total=False): yahoo.com, etc.) and disposable email addresses are not allowed. """ - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] - """Optional parameter to force the language of the retrieved brand data.""" + """Language to force for the retrieved brand data.""" - max_speed: Annotated[bool, PropertyInfo(alias="maxSpeed")] + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """ + Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + """ + + max_speed: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="maxSpeed")] """Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. """ + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. diff --git a/src/brand/dev/types/brand_retrieve_by_email_response.py b/src/brand/dev/types/brand_retrieve_by_email_response.py index 922fa75b..4d36c597 100644 --- a/src/brand/dev/types/brand_retrieve_by_email_response.py +++ b/src/brand/dev/types/brand_retrieve_by_email_response.py @@ -21,6 +21,7 @@ "BrandLogoResolution", "BrandSocial", "BrandStock", + "KeyMetadata", ] @@ -169,7 +170,6 @@ class BrandIndustriesEic(BaseModel): "Streaming Platforms (Video, Music, Audio)", "Gaming & Interactive Entertainment", "Creator Economy & Influencer Platforms", - "Advertising, Adtech & Media Buying", "Film, TV & Production Studios", "Events, Venues & Live Entertainment", "Virtual Worlds & Metaverse Experiences", @@ -230,6 +230,7 @@ class BrandIndustriesEic(BaseModel): "Streetwear & Emerging Luxury", "Couture & Made-to-Measure", "News Publishing & Journalism", + "Advertising, Adtech & Media Buying", "Digital Media & Content Platforms", "Broadcasting (TV & Radio)", "Podcasting & Audio Media", @@ -415,8 +416,42 @@ class BrandLogo(BaseModel): class BrandSocial(BaseModel): - type: Optional[str] = None - """Type of social media, e.g., 'facebook', 'twitter'""" + type: Optional[ + Literal[ + "x", + "facebook", + "instagram", + "linkedin", + "youtube", + "pinterest", + "tiktok", + "dribbble", + "github", + "behance", + "snapchat", + "whatsapp", + "telegram", + "line", + "discord", + "twitch", + "vimeo", + "imdb", + "tumblr", + "flickr", + "giphy", + "medium", + "spotify", + "soundcloud", + "tripadvisor", + "yelp", + "producthunt", + "reddit", + "crunchbase", + "appstore", + "playstore", + ] + ] = None + """Type of social media platform""" url: Optional[str] = None """URL of the social media page""" @@ -470,6 +505,132 @@ class Brand(BaseModel): phone: Optional[str] = None """Company phone number""" + primary_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] + ] = None + """Language to force for the retrieved brand data.""" + slogan: Optional[str] = None """The brand's slogan""" @@ -486,6 +647,19 @@ class Brand(BaseModel): """The title or name of the brand""" +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class BrandRetrieveByEmailResponse(BaseModel): brand: Optional[Brand] = None """Detailed brand information""" @@ -493,5 +667,12 @@ class BrandRetrieveByEmailResponse(BaseModel): code: Optional[int] = None """HTTP status code""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + status: Optional[str] = None """Status of the response, e.g., 'ok'""" diff --git a/src/brand/dev/types/brand_retrieve_by_isin_params.py b/src/brand/dev/types/brand_retrieve_by_isin_params.py index db559fae..ae66cb2a 100644 --- a/src/brand/dev/types/brand_retrieve_by_isin_params.py +++ b/src/brand/dev/types/brand_retrieve_by_isin_params.py @@ -2,8 +2,10 @@ from __future__ import annotations +from typing import Union, Optional from typing_extensions import Literal, Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandRetrieveByIsinParams"] @@ -17,72 +19,154 @@ class BrandRetrieveByIsinParams(TypedDict, total=False): followed by 9 alphanumeric characters and ending with a digit. """ - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] - """Optional parameter to force the language of the retrieved brand data.""" + """Language to force for the retrieved brand data.""" - max_speed: Annotated[bool, PropertyInfo(alias="maxSpeed")] + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """ + Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + """ + + max_speed: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="maxSpeed")] """Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. """ + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. diff --git a/src/brand/dev/types/brand_retrieve_by_isin_response.py b/src/brand/dev/types/brand_retrieve_by_isin_response.py index 21a860e4..cf141543 100644 --- a/src/brand/dev/types/brand_retrieve_by_isin_response.py +++ b/src/brand/dev/types/brand_retrieve_by_isin_response.py @@ -21,6 +21,7 @@ "BrandLogoResolution", "BrandSocial", "BrandStock", + "KeyMetadata", ] @@ -169,7 +170,6 @@ class BrandIndustriesEic(BaseModel): "Streaming Platforms (Video, Music, Audio)", "Gaming & Interactive Entertainment", "Creator Economy & Influencer Platforms", - "Advertising, Adtech & Media Buying", "Film, TV & Production Studios", "Events, Venues & Live Entertainment", "Virtual Worlds & Metaverse Experiences", @@ -230,6 +230,7 @@ class BrandIndustriesEic(BaseModel): "Streetwear & Emerging Luxury", "Couture & Made-to-Measure", "News Publishing & Journalism", + "Advertising, Adtech & Media Buying", "Digital Media & Content Platforms", "Broadcasting (TV & Radio)", "Podcasting & Audio Media", @@ -415,8 +416,42 @@ class BrandLogo(BaseModel): class BrandSocial(BaseModel): - type: Optional[str] = None - """Type of social media, e.g., 'facebook', 'twitter'""" + type: Optional[ + Literal[ + "x", + "facebook", + "instagram", + "linkedin", + "youtube", + "pinterest", + "tiktok", + "dribbble", + "github", + "behance", + "snapchat", + "whatsapp", + "telegram", + "line", + "discord", + "twitch", + "vimeo", + "imdb", + "tumblr", + "flickr", + "giphy", + "medium", + "spotify", + "soundcloud", + "tripadvisor", + "yelp", + "producthunt", + "reddit", + "crunchbase", + "appstore", + "playstore", + ] + ] = None + """Type of social media platform""" url: Optional[str] = None """URL of the social media page""" @@ -470,6 +505,132 @@ class Brand(BaseModel): phone: Optional[str] = None """Company phone number""" + primary_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] + ] = None + """Language to force for the retrieved brand data.""" + slogan: Optional[str] = None """The brand's slogan""" @@ -486,6 +647,19 @@ class Brand(BaseModel): """The title or name of the brand""" +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class BrandRetrieveByIsinResponse(BaseModel): brand: Optional[Brand] = None """Detailed brand information""" @@ -493,5 +667,12 @@ class BrandRetrieveByIsinResponse(BaseModel): code: Optional[int] = None """HTTP status code""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + status: Optional[str] = None """Status of the response, e.g., 'ok'""" diff --git a/src/brand/dev/types/brand_retrieve_by_name_params.py b/src/brand/dev/types/brand_retrieve_by_name_params.py index 847bdb3f..fc440cf7 100644 --- a/src/brand/dev/types/brand_retrieve_by_name_params.py +++ b/src/brand/dev/types/brand_retrieve_by_name_params.py @@ -2,8 +2,10 @@ from __future__ import annotations +from typing import Union, Optional from typing_extensions import Literal, Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandRetrieveByNameParams"] @@ -17,317 +19,399 @@ class BrandRetrieveByNameParams(TypedDict, total=False): """ country_gl: Literal[ - "ad", - "ae", "af", - "ag", - "ai", "al", - "am", - "an", + "dz", + "as", + "ad", "ao", + "ai", "aq", + "ag", "ar", - "as", - "at", - "au", + "am", "aw", + "au", + "at", "az", - "ba", - "bb", + "bs", + "bh", "bd", + "bb", + "by", "be", - "bf", - "bg", - "bh", - "bi", + "bz", "bj", "bm", - "bn", - "bo", - "br", - "bs", "bt", - "bv", + "bo", + "ba", "bw", - "by", - "bz", + "bv", + "br", + "io", + "bn", + "bg", + "bf", + "bi", + "kh", + "cm", "ca", - "cc", - "cd", + "cv", + "ky", "cf", - "cg", - "ch", - "ci", - "ck", + "td", "cl", - "cm", "cn", + "cx", + "cc", "co", + "km", + "cg", + "cd", + "ck", "cr", + "ci", + "hr", "cu", - "cv", - "cx", "cy", "cz", - "de", - "dj", "dk", + "dj", "dm", "do", - "dz", "ec", - "ee", "eg", - "eh", + "sv", + "gq", "er", - "es", + "ee", "et", - "fi", - "fj", "fk", - "fm", "fo", + "fj", + "fi", "fr", + "gf", + "pf", + "tf", "ga", - "gb", - "gd", + "gm", "ge", - "gf", + "de", "gh", "gi", + "gr", "gl", - "gm", - "gn", + "gd", "gp", - "gq", - "gr", - "gs", - "gt", "gu", + "gt", + "gn", "gw", "gy", - "hk", + "ht", "hm", + "va", "hn", - "hr", - "ht", + "hk", "hu", + "is", + "in", "id", + "ir", + "iq", "ie", "il", - "in", - "io", - "iq", - "ir", - "is", "it", "jm", - "jo", "jp", + "jo", + "kz", "ke", - "kg", - "kh", "ki", - "km", - "kn", "kp", "kr", "kw", - "ky", - "kz", + "kg", "la", + "lv", "lb", - "lc", - "li", - "lk", - "lr", "ls", + "lr", + "ly", + "li", "lt", "lu", - "lv", - "ly", - "ma", - "mc", - "md", - "mg", - "mh", + "mo", "mk", + "mg", + "mw", + "my", + "mv", "ml", - "mm", - "mn", - "mo", - "mp", + "mt", + "mh", "mq", "mr", - "ms", - "mt", "mu", - "mv", - "mw", + "yt", "mx", - "my", + "fm", + "md", + "mc", + "mn", + "ms", + "ma", "mz", + "mm", "na", + "nr", + "np", + "nl", + "an", "nc", + "nz", + "ni", "ne", - "nf", "ng", - "ni", - "nl", - "no", - "np", - "nr", "nu", - "nz", + "nf", + "mp", + "no", "om", + "pk", + "pw", + "ps", "pa", - "pe", - "pf", "pg", + "py", + "pe", "ph", - "pk", - "pl", - "pm", "pn", - "pr", - "ps", + "pl", "pt", - "pw", - "py", + "pr", "qa", "re", "ro", - "rs", "ru", "rw", + "sh", + "kn", + "lc", + "pm", + "vc", + "ws", + "sm", + "st", "sa", - "sb", + "sn", + "rs", "sc", - "sd", - "se", + "sl", "sg", - "sh", - "si", - "sj", "sk", - "sl", - "sm", - "sn", + "si", + "sb", "so", + "za", + "gs", + "es", + "lk", + "sd", "sr", - "st", - "sv", - "sy", + "sj", "sz", - "tc", - "td", - "tf", - "tg", - "th", + "se", + "ch", + "sy", + "tw", "tj", - "tk", + "tz", + "th", "tl", - "tm", - "tn", + "tg", + "tk", "to", - "tr", "tt", + "tn", + "tr", + "tm", + "tc", "tv", - "tw", - "tz", - "ua", "ug", - "um", + "ua", + "ae", + "gb", "us", + "um", "uy", "uz", - "va", - "vc", + "vu", "ve", + "vn", "vg", "vi", - "vn", - "vu", "wf", - "ws", + "eh", "ye", - "yt", - "za", "zm", "zw", ] - """Optional country code (GL parameter) to specify the country. - - This affects the geographic location used for search queries. + """ + Two-letter ISO 3166-1 alpha-2 country code (GL parameter) used to localize + search. """ - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] - """Optional parameter to force the language of the retrieved brand data.""" + """Language to force for the retrieved brand data.""" + + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """ + Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + """ - max_speed: Annotated[bool, PropertyInfo(alias="maxSpeed")] + max_speed: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="maxSpeed")] """Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. """ + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. diff --git a/src/brand/dev/types/brand_retrieve_by_name_response.py b/src/brand/dev/types/brand_retrieve_by_name_response.py index 1e462e7c..9b02daa5 100644 --- a/src/brand/dev/types/brand_retrieve_by_name_response.py +++ b/src/brand/dev/types/brand_retrieve_by_name_response.py @@ -21,6 +21,7 @@ "BrandLogoResolution", "BrandSocial", "BrandStock", + "KeyMetadata", ] @@ -169,7 +170,6 @@ class BrandIndustriesEic(BaseModel): "Streaming Platforms (Video, Music, Audio)", "Gaming & Interactive Entertainment", "Creator Economy & Influencer Platforms", - "Advertising, Adtech & Media Buying", "Film, TV & Production Studios", "Events, Venues & Live Entertainment", "Virtual Worlds & Metaverse Experiences", @@ -230,6 +230,7 @@ class BrandIndustriesEic(BaseModel): "Streetwear & Emerging Luxury", "Couture & Made-to-Measure", "News Publishing & Journalism", + "Advertising, Adtech & Media Buying", "Digital Media & Content Platforms", "Broadcasting (TV & Radio)", "Podcasting & Audio Media", @@ -415,8 +416,42 @@ class BrandLogo(BaseModel): class BrandSocial(BaseModel): - type: Optional[str] = None - """Type of social media, e.g., 'facebook', 'twitter'""" + type: Optional[ + Literal[ + "x", + "facebook", + "instagram", + "linkedin", + "youtube", + "pinterest", + "tiktok", + "dribbble", + "github", + "behance", + "snapchat", + "whatsapp", + "telegram", + "line", + "discord", + "twitch", + "vimeo", + "imdb", + "tumblr", + "flickr", + "giphy", + "medium", + "spotify", + "soundcloud", + "tripadvisor", + "yelp", + "producthunt", + "reddit", + "crunchbase", + "appstore", + "playstore", + ] + ] = None + """Type of social media platform""" url: Optional[str] = None """URL of the social media page""" @@ -470,6 +505,132 @@ class Brand(BaseModel): phone: Optional[str] = None """Company phone number""" + primary_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] + ] = None + """Language to force for the retrieved brand data.""" + slogan: Optional[str] = None """The brand's slogan""" @@ -486,6 +647,19 @@ class Brand(BaseModel): """The title or name of the brand""" +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class BrandRetrieveByNameResponse(BaseModel): brand: Optional[Brand] = None """Detailed brand information""" @@ -493,5 +667,12 @@ class BrandRetrieveByNameResponse(BaseModel): code: Optional[int] = None """HTTP status code""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + status: Optional[str] = None """Status of the response, e.g., 'ok'""" diff --git a/src/brand/dev/types/brand_retrieve_by_ticker_params.py b/src/brand/dev/types/brand_retrieve_by_ticker_params.py index d3283850..d44ced3f 100644 --- a/src/brand/dev/types/brand_retrieve_by_ticker_params.py +++ b/src/brand/dev/types/brand_retrieve_by_ticker_params.py @@ -2,8 +2,10 @@ from __future__ import annotations +from typing import Union, Optional from typing_extensions import Literal, Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandRetrieveByTickerParams"] @@ -16,72 +18,154 @@ class BrandRetrieveByTickerParams(TypedDict, total=False): Must be 1-15 characters, letters/numbers/dots only. """ - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] - """Optional parameter to force the language of the retrieved brand data.""" + """Language to force for the retrieved brand data.""" - max_speed: Annotated[bool, PropertyInfo(alias="maxSpeed")] + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """ + Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + """ + + max_speed: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="maxSpeed")] """Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster response at the cost of less comprehensive data. """ + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + ticker_exchange: Literal[ "AMEX", "AMS", @@ -156,7 +240,7 @@ class BrandRetrieveByTickerParams(TypedDict, total=False): "WSE", "XETRA", ] - """Optional stock exchange for the ticker. Defaults to NASDAQ if not specified.""" + """Stock exchange code.""" timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. diff --git a/src/brand/dev/types/brand_retrieve_by_ticker_response.py b/src/brand/dev/types/brand_retrieve_by_ticker_response.py index 9815a65a..29e1af97 100644 --- a/src/brand/dev/types/brand_retrieve_by_ticker_response.py +++ b/src/brand/dev/types/brand_retrieve_by_ticker_response.py @@ -21,6 +21,7 @@ "BrandLogoResolution", "BrandSocial", "BrandStock", + "KeyMetadata", ] @@ -169,7 +170,6 @@ class BrandIndustriesEic(BaseModel): "Streaming Platforms (Video, Music, Audio)", "Gaming & Interactive Entertainment", "Creator Economy & Influencer Platforms", - "Advertising, Adtech & Media Buying", "Film, TV & Production Studios", "Events, Venues & Live Entertainment", "Virtual Worlds & Metaverse Experiences", @@ -230,6 +230,7 @@ class BrandIndustriesEic(BaseModel): "Streetwear & Emerging Luxury", "Couture & Made-to-Measure", "News Publishing & Journalism", + "Advertising, Adtech & Media Buying", "Digital Media & Content Platforms", "Broadcasting (TV & Radio)", "Podcasting & Audio Media", @@ -415,8 +416,42 @@ class BrandLogo(BaseModel): class BrandSocial(BaseModel): - type: Optional[str] = None - """Type of social media, e.g., 'facebook', 'twitter'""" + type: Optional[ + Literal[ + "x", + "facebook", + "instagram", + "linkedin", + "youtube", + "pinterest", + "tiktok", + "dribbble", + "github", + "behance", + "snapchat", + "whatsapp", + "telegram", + "line", + "discord", + "twitch", + "vimeo", + "imdb", + "tumblr", + "flickr", + "giphy", + "medium", + "spotify", + "soundcloud", + "tripadvisor", + "yelp", + "producthunt", + "reddit", + "crunchbase", + "appstore", + "playstore", + ] + ] = None + """Type of social media platform""" url: Optional[str] = None """URL of the social media page""" @@ -470,6 +505,132 @@ class Brand(BaseModel): phone: Optional[str] = None """Company phone number""" + primary_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] + ] = None + """Language to force for the retrieved brand data.""" + slogan: Optional[str] = None """The brand's slogan""" @@ -486,6 +647,19 @@ class Brand(BaseModel): """The title or name of the brand""" +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class BrandRetrieveByTickerResponse(BaseModel): brand: Optional[Brand] = None """Detailed brand information""" @@ -493,5 +667,12 @@ class BrandRetrieveByTickerResponse(BaseModel): code: Optional[int] = None """HTTP status code""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + status: Optional[str] = None """Status of the response, e.g., 'ok'""" diff --git a/src/brand/dev/types/brand_retrieve_naics_params.py b/src/brand/dev/types/brand_retrieve_naics_params.py index 2803c134..4ac68536 100644 --- a/src/brand/dev/types/brand_retrieve_naics_params.py +++ b/src/brand/dev/types/brand_retrieve_naics_params.py @@ -4,6 +4,7 @@ from typing_extensions import Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandRetrieveNaicsParams"] @@ -13,8 +14,8 @@ class BrandRetrieveNaicsParams(TypedDict, total=False): input: Required[str] """Brand domain or title to retrieve NAICS code for. - If a valid domain is provided in `input`, it will be used for classification, - otherwise, we will search for the brand using the provided title. + If a valid domain is provided, it will be used for classification, otherwise, we + will search for the brand using the provided title. """ max_results: Annotated[int, PropertyInfo(alias="maxResults")] @@ -26,6 +27,13 @@ class BrandRetrieveNaicsParams(TypedDict, total=False): min_results: Annotated[int, PropertyInfo(alias="minResults")] """Minimum number of NAICS codes to return. Must be at least 1. Defaults to 1.""" + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. diff --git a/src/brand/dev/types/brand_retrieve_naics_response.py b/src/brand/dev/types/brand_retrieve_naics_response.py index a53da5e4..4783dc35 100644 --- a/src/brand/dev/types/brand_retrieve_naics_response.py +++ b/src/brand/dev/types/brand_retrieve_naics_response.py @@ -5,7 +5,7 @@ from .._models import BaseModel -__all__ = ["BrandRetrieveNaicsResponse", "Code"] +__all__ = ["BrandRetrieveNaicsResponse", "Code", "KeyMetadata"] class Code(BaseModel): @@ -19,6 +19,19 @@ class Code(BaseModel): """NAICS title""" +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class BrandRetrieveNaicsResponse(BaseModel): codes: Optional[List[Code]] = None """Array of NAICS codes and titles.""" @@ -26,6 +39,13 @@ class BrandRetrieveNaicsResponse(BaseModel): domain: Optional[str] = None """Domain found for the brand""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + status: Optional[str] = None """Status of the response, e.g., 'ok'""" diff --git a/src/brand/dev/types/brand_retrieve_params.py b/src/brand/dev/types/brand_retrieve_params.py index 03e102aa..3f4947cb 100644 --- a/src/brand/dev/types/brand_retrieve_params.py +++ b/src/brand/dev/types/brand_retrieve_params.py @@ -2,83 +2,157 @@ from __future__ import annotations -from typing_extensions import Literal, Required, Annotated, TypedDict +from typing import Union, Optional +from typing_extensions import Literal, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandRetrieveParams"] class BrandRetrieveParams(TypedDict, total=False): - domain: Required[str] + domain: str """Domain name to retrieve brand data for (e.g., 'example.com', 'google.com'). Cannot be used with name or ticker parameters. """ - force_language: Literal[ - "albanian", - "arabic", - "azeri", - "bengali", - "bulgarian", - "cantonese", - "cebuano", - "croatian", - "czech", - "danish", - "dutch", - "english", - "estonian", - "farsi", - "finnish", - "french", - "german", - "hausa", - "hawaiian", - "hindi", - "hungarian", - "icelandic", - "indonesian", - "italian", - "kazakh", - "korean", - "kyrgyz", - "latin", - "latvian", - "lithuanian", - "macedonian", - "mongolian", - "nepali", - "norwegian", - "pashto", - "pidgin", - "polish", - "portuguese", - "romanian", - "russian", - "serbian", - "slovak", - "slovene", - "somali", - "spanish", - "swahili", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "uzbek", - "vietnamese", - "welsh", + force_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] ] - """Optional parameter to force the language of the retrieved brand data. + """Language to force for the retrieved brand data.""" - Works with all three lookup methods. + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """ + Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. """ - max_speed: Annotated[bool, PropertyInfo(alias="maxSpeed")] + max_speed: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="maxSpeed")] """Optional parameter to optimize the API call for maximum speed. When set to true, the API will skip time-consuming operations for faster @@ -86,6 +160,101 @@ class BrandRetrieveParams(TypedDict, total=False): methods. """ + name: str + """Company name to retrieve brand data for (e.g., 'Apple Inc'). + + Cannot be used with domain or ticker parameters. + """ + + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + + ticker: str + """Stock ticker symbol to retrieve brand data for (e.g., 'AAPL'). + + Cannot be used with domain or name parameters. + """ + + ticker_exchange: Literal[ + "AMEX", + "AMS", + "AQS", + "ASX", + "ATH", + "BER", + "BME", + "BRU", + "BSE", + "BUD", + "BUE", + "BVC", + "CBOE", + "CNQ", + "CPH", + "DFM", + "DOH", + "DUB", + "DUS", + "DXE", + "EGX", + "FSX", + "HAM", + "HEL", + "HKSE", + "HOSE", + "ICE", + "IOB", + "IST", + "JKT", + "JNB", + "JPX", + "KLS", + "KOE", + "KSC", + "KUW", + "LIS", + "LSE", + "MCX", + "MEX", + "MIL", + "MUN", + "NASDAQ", + "NEO", + "NSE", + "NYSE", + "NZE", + "OSL", + "OTC", + "PAR", + "PNK", + "PRA", + "RIS", + "SAO", + "SAU", + "SES", + "SET", + "SGO", + "SHH", + "SHZ", + "SIX", + "STO", + "STU", + "TAI", + "TAL", + "TLV", + "TSX", + "TSXV", + "TWO", + "VIE", + "WSE", + "XETRA", + ] + """Stock exchange code.""" + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. diff --git a/src/brand/dev/types/brand_retrieve_response.py b/src/brand/dev/types/brand_retrieve_response.py index 28aea6f0..51fdb595 100644 --- a/src/brand/dev/types/brand_retrieve_response.py +++ b/src/brand/dev/types/brand_retrieve_response.py @@ -21,6 +21,7 @@ "BrandLogoResolution", "BrandSocial", "BrandStock", + "KeyMetadata", ] @@ -169,7 +170,6 @@ class BrandIndustriesEic(BaseModel): "Streaming Platforms (Video, Music, Audio)", "Gaming & Interactive Entertainment", "Creator Economy & Influencer Platforms", - "Advertising, Adtech & Media Buying", "Film, TV & Production Studios", "Events, Venues & Live Entertainment", "Virtual Worlds & Metaverse Experiences", @@ -230,6 +230,7 @@ class BrandIndustriesEic(BaseModel): "Streetwear & Emerging Luxury", "Couture & Made-to-Measure", "News Publishing & Journalism", + "Advertising, Adtech & Media Buying", "Digital Media & Content Platforms", "Broadcasting (TV & Radio)", "Podcasting & Audio Media", @@ -415,8 +416,42 @@ class BrandLogo(BaseModel): class BrandSocial(BaseModel): - type: Optional[str] = None - """Type of social media, e.g., 'facebook', 'twitter'""" + type: Optional[ + Literal[ + "x", + "facebook", + "instagram", + "linkedin", + "youtube", + "pinterest", + "tiktok", + "dribbble", + "github", + "behance", + "snapchat", + "whatsapp", + "telegram", + "line", + "discord", + "twitch", + "vimeo", + "imdb", + "tumblr", + "flickr", + "giphy", + "medium", + "spotify", + "soundcloud", + "tripadvisor", + "yelp", + "producthunt", + "reddit", + "crunchbase", + "appstore", + "playstore", + ] + ] = None + """Type of social media platform""" url: Optional[str] = None """URL of the social media page""" @@ -470,6 +505,132 @@ class Brand(BaseModel): phone: Optional[str] = None """Company phone number""" + primary_language: Optional[ + Literal[ + "afrikaans", + "albanian", + "amharic", + "arabic", + "armenian", + "assamese", + "aymara", + "azeri", + "basque", + "belarusian", + "bengali", + "bosnian", + "bulgarian", + "burmese", + "cantonese", + "catalan", + "cebuano", + "chinese", + "corsican", + "croatian", + "czech", + "danish", + "dutch", + "english", + "esperanto", + "estonian", + "farsi", + "fijian", + "finnish", + "french", + "galician", + "georgian", + "german", + "greek", + "guarani", + "gujarati", + "haitian-creole", + "hausa", + "hawaiian", + "hebrew", + "hindi", + "hmong", + "hungarian", + "icelandic", + "igbo", + "indonesian", + "irish", + "italian", + "japanese", + "javanese", + "kannada", + "kazakh", + "khmer", + "kinyarwanda", + "korean", + "kurdish", + "kyrgyz", + "lao", + "latin", + "latvian", + "lingala", + "lithuanian", + "luxembourgish", + "macedonian", + "malagasy", + "malay", + "malayalam", + "maltese", + "maori", + "marathi", + "mongolian", + "nepali", + "norwegian", + "odia", + "oromo", + "pashto", + "pidgin", + "polish", + "portuguese", + "punjabi", + "quechua", + "romanian", + "russian", + "samoan", + "scottish-gaelic", + "serbian", + "sesotho", + "shona", + "sindhi", + "sinhala", + "slovak", + "slovene", + "somali", + "spanish", + "sundanese", + "swahili", + "swedish", + "tagalog", + "tajik", + "tamil", + "tatar", + "telugu", + "thai", + "tibetan", + "tigrinya", + "tongan", + "tswana", + "turkish", + "turkmen", + "ukrainian", + "urdu", + "uyghur", + "uzbek", + "vietnamese", + "welsh", + "wolof", + "xhosa", + "yiddish", + "yoruba", + "zulu", + ] + ] = None + """Language to force for the retrieved brand data.""" + slogan: Optional[str] = None """The brand's slogan""" @@ -486,6 +647,19 @@ class Brand(BaseModel): """The title or name of the brand""" +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class BrandRetrieveResponse(BaseModel): brand: Optional[Brand] = None """Detailed brand information""" @@ -493,5 +667,12 @@ class BrandRetrieveResponse(BaseModel): code: Optional[int] = None """HTTP status code""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + status: Optional[str] = None """Status of the response, e.g., 'ok'""" diff --git a/src/brand/dev/types/brand_retrieve_simplified_params.py b/src/brand/dev/types/brand_retrieve_simplified_params.py index b9d9cd3f..1f9f6d2f 100644 --- a/src/brand/dev/types/brand_retrieve_simplified_params.py +++ b/src/brand/dev/types/brand_retrieve_simplified_params.py @@ -2,8 +2,10 @@ from __future__ import annotations -from typing_extensions import Required, Annotated, TypedDict +from typing import Optional +from typing_extensions import Literal, Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandRetrieveSimplifiedParams"] @@ -13,6 +15,24 @@ class BrandRetrieveSimplifiedParams(TypedDict, total=False): domain: Required[str] """Domain name to retrieve simplified brand data for""" + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """ + Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + """ + + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + + theme: Literal["light", "dark"] + """Optional theme preference used when selecting brand assets.""" + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] """Optional timeout in milliseconds for the request. diff --git a/src/brand/dev/types/brand_retrieve_simplified_response.py b/src/brand/dev/types/brand_retrieve_simplified_response.py index 819e408d..6684272d 100644 --- a/src/brand/dev/types/brand_retrieve_simplified_response.py +++ b/src/brand/dev/types/brand_retrieve_simplified_response.py @@ -15,6 +15,7 @@ "BrandLogo", "BrandLogoColor", "BrandLogoResolution", + "KeyMetadata", ] @@ -119,6 +120,19 @@ class Brand(BaseModel): """The title or name of the brand""" +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class BrandRetrieveSimplifiedResponse(BaseModel): brand: Optional[Brand] = None """Simplified brand information""" @@ -126,5 +140,12 @@ class BrandRetrieveSimplifiedResponse(BaseModel): code: Optional[int] = None """HTTP status code of the response""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + status: Optional[str] = None """Status of the response, e.g., 'ok'""" diff --git a/src/brand/dev/types/brand_screenshot_params.py b/src/brand/dev/types/brand_screenshot_params.py index 4f26b1fb..6f4622d4 100644 --- a/src/brand/dev/types/brand_screenshot_params.py +++ b/src/brand/dev/types/brand_screenshot_params.py @@ -2,18 +2,245 @@ from __future__ import annotations -from typing_extensions import Literal, Required, Annotated, TypedDict +from typing import Union, Optional +from typing_extensions import Literal, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo -__all__ = ["BrandScreenshotParams"] +__all__ = ["BrandScreenshotParams", "Viewport"] class BrandScreenshotParams(TypedDict, total=False): - domain: Required[str] + color_scheme: Annotated[Literal["light", "dark"], PropertyInfo(alias="colorScheme")] + """Optional parameter to choose the site's visual theme in the screenshot. + + Use 'light' or 'dark' when the site offers both appearances. + """ + + country: Literal[ + "ad", + "ae", + "af", + "ag", + "ai", + "al", + "am", + "ao", + "ar", + "at", + "au", + "aw", + "az", + "ba", + "bb", + "bd", + "be", + "bf", + "bg", + "bh", + "bi", + "bj", + "bm", + "bn", + "bo", + "bq", + "br", + "bs", + "bw", + "by", + "bz", + "ca", + "cd", + "cf", + "cg", + "ch", + "ci", + "cl", + "cm", + "cn", + "co", + "cr", + "cv", + "cw", + "cy", + "cz", + "de", + "dj", + "dk", + "dm", + "do", + "dz", + "ec", + "ee", + "eg", + "es", + "et", + "fi", + "fj", + "fr", + "ga", + "gb", + "gd", + "ge", + "gf", + "gg", + "gh", + "gm", + "gn", + "gp", + "gq", + "gr", + "gt", + "gu", + "gw", + "gy", + "hk", + "hn", + "hr", + "ht", + "hu", + "id", + "ie", + "il", + "im", + "in", + "iq", + "ir", + "is", + "it", + "je", + "jm", + "jo", + "jp", + "ke", + "kg", + "kh", + "kn", + "kr", + "kw", + "ky", + "kz", + "la", + "lb", + "lc", + "lk", + "lr", + "ls", + "lt", + "lu", + "lv", + "ly", + "ma", + "mc", + "md", + "me", + "mf", + "mg", + "mk", + "ml", + "mm", + "mn", + "mo", + "mq", + "mr", + "mt", + "mu", + "mv", + "mw", + "mx", + "my", + "mz", + "na", + "nc", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nz", + "om", + "pa", + "pe", + "pf", + "pg", + "ph", + "pk", + "pl", + "pr", + "ps", + "pt", + "py", + "qa", + "re", + "ro", + "rs", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sr", + "ss", + "st", + "sv", + "sx", + "sy", + "sz", + "tc", + "td", + "tg", + "th", + "tj", + "tl", + "tm", + "tn", + "tr", + "tt", + "tw", + "tz", + "ua", + "ug", + "us", + "uy", + "uz", + "vc", + "ve", + "vg", + "vi", + "vn", + "ye", + "yt", + "za", + "zm", + "zw", + ] + """ + Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). + """ + + direct_url: Annotated[str, PropertyInfo(alias="directUrl")] + """ + A specific URL to screenshot directly, bypassing domain resolution (e.g., + 'https://example.com/pricing'). When provided, the screenshot is taken of this + exact URL. You must provide either 'domain' or 'directUrl', but not both. + """ + + domain: str """Domain name to take screenshot of (e.g., 'example.com', 'google.com'). - The domain will be automatically normalized and validated. + The domain will be automatically normalized and validated. You must provide + either 'domain' or 'directUrl', but not both. """ full_screenshot: Annotated[Literal["true", "false"], PropertyInfo(alias="fullScreenshot")] @@ -23,18 +250,77 @@ class BrandScreenshotParams(TypedDict, total=False): provided, takes a viewport screenshot (standard browser view). """ + handle_cookie_popup: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="handleCookiePopup")] + """Optional parameter to control cookie/consent popup handling. + + If 'true', we dismiss cookie banner before capture. If 'false' or not provided, + captures the page without that step. + """ + + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """ + Return a cached screenshot if a prior screenshot for the same parameters exists + and is younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always capture fresh. + """ + page: Literal["login", "signup", "blog", "careers", "pricing", "terms", "privacy", "contact"] """Optional parameter to specify which page type to screenshot. If provided, the system will scrape the domain's links and use heuristics to find the most appropriate URL for the specified page type (30 supported - languages). If not provided, screenshots the main domain landing page. + languages). If not provided, screenshots the main domain landing page. Only + applicable when using 'domain', not 'directUrl'. + """ + + scroll_offset: Annotated[Optional[int], PropertyInfo(alias="scrollOffset")] + """ + Optional vertical scroll offset in pixels for capturing a long page in + viewport-sized chunks. When provided, the full page is captured once and the + returned image is the viewport-sized slice that begins at this Y offset (e.g. + request scrollOffset=0, then 1080, then 2160 to walk a 1920x1080 landing page + top to bottom). The final slice may be shorter than the viewport height. Takes + precedence over fullScreenshot. Max: 100000. + """ + + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] + """Optional timeout in milliseconds for the request. + + If the request takes longer than this value, it will be aborted with a 408 + status code. Maximum allowed value is 300000ms (5 minutes). """ - prioritize: Literal["speed", "quality"] - """Optional parameter to prioritize screenshot capture. + viewport: Viewport + """Optional browser viewport dimensions for the screenshot. Defaults to 1920x1080.""" - If 'speed', optimizes for faster capture with basic quality. If 'quality', - optimizes for higher quality with longer wait times. Defaults to 'quality' if - not provided. + wait_for_ms: Annotated[Optional[int], PropertyInfo(alias="waitForMs")] """ + Optional browser wait time in milliseconds after initial page load before taking + the screenshot. Min: 0. Max: 30000 (30 seconds). Defaults to 3000 ms when + omitted. + """ + + zdr: Literal["enabled", "disabled"] + """ + Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. + """ + + +class Viewport(TypedDict, total=False): + """Optional browser viewport dimensions for the screenshot. Defaults to 1920x1080.""" + + height: int + """Viewport height in pixels.""" + + width: int + """Viewport width in pixels.""" diff --git a/src/brand/dev/types/brand_screenshot_response.py b/src/brand/dev/types/brand_screenshot_response.py index c43ae741..ac7d301f 100644 --- a/src/brand/dev/types/brand_screenshot_response.py +++ b/src/brand/dev/types/brand_screenshot_response.py @@ -7,7 +7,20 @@ from .._models import BaseModel -__all__ = ["BrandScreenshotResponse"] +__all__ = ["BrandScreenshotResponse", "KeyMetadata"] + + +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" class BrandScreenshotResponse(BaseModel): @@ -17,11 +30,27 @@ class BrandScreenshotResponse(BaseModel): domain: Optional[str] = None """The normalized domain that was processed""" + height: Optional[int] = None + """Height in pixels of the returned screenshot image""" + + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + screenshot: Optional[str] = None - """Public URL of the uploaded screenshot image""" + """ + Public image URL for standard requests, or an in-memory data URL when ZDR is + enabled. + """ screenshot_type: Optional[Literal["viewport", "fullPage"]] = FieldInfo(alias="screenshotType", default=None) """Type of screenshot that was captured""" status: Optional[str] = None """Status of the response, e.g., 'ok'""" + + width: Optional[int] = None + """Width in pixels of the returned screenshot image""" diff --git a/src/brand/dev/types/brand_styleguide_params.py b/src/brand/dev/types/brand_styleguide_params.py index 9c858b54..e649f8c3 100644 --- a/src/brand/dev/types/brand_styleguide_params.py +++ b/src/brand/dev/types/brand_styleguide_params.py @@ -2,24 +2,50 @@ from __future__ import annotations -from typing_extensions import Annotated, TypedDict +from typing import Optional +from typing_extensions import Literal, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandStyleguideParams"] class BrandStyleguideParams(TypedDict, total=False): + color_scheme: Annotated[Literal["light", "dark"], PropertyInfo(alias="colorScheme")] + """ + Optional browser color scheme to emulate for websites that respond to + prefers-color-scheme. This value is part of the styleguide cache key. + """ + direct_url: Annotated[str, PropertyInfo(alias="directUrl")] """ A specific URL to fetch the styleguide from directly, bypassing domain - resolution (e.g., 'https://example.com/design-system'). + resolution (e.g., 'https://example.com/design-system'). When provided, the + styleguide is extracted from this exact URL. You must provide either 'domain' or + 'directUrl', but not both. """ domain: str """Domain name to extract styleguide from (e.g., 'example.com', 'google.com'). - The domain will be automatically normalized and validated. + The domain will be automatically normalized and validated. You must provide + either 'domain' or 'directUrl', but not both. + """ + + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """ + Maximum age in milliseconds for cached brand data before the API performs a hard + refresh. Defaults to 3 months (7776000000 ms). Values below 1 day (86400000 ms) + are clamped to 1 day; values above 1 year (31536000000 ms) are clamped to 1 + year. + """ + + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. """ timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] diff --git a/src/brand/dev/types/brand_styleguide_response.py b/src/brand/dev/types/brand_styleguide_response.py index edc2d296..68b2198f 100644 --- a/src/brand/dev/types/brand_styleguide_response.py +++ b/src/brand/dev/types/brand_styleguide_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -9,6 +9,7 @@ __all__ = [ "BrandStyleguideResponse", + "KeyMetadata", "Styleguide", "StyleguideColors", "StyleguideComponents", @@ -18,6 +19,7 @@ "StyleguideComponentsButtonSecondary", "StyleguideComponentsCard", "StyleguideElementSpacing", + "StyleguideFontLinks", "StyleguideShadows", "StyleguideTypography", "StyleguideTypographyHeadings", @@ -29,6 +31,19 @@ ] +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class StyleguideColors(BaseModel): """Primary colors used on the website""" @@ -244,6 +259,30 @@ class StyleguideElementSpacing(BaseModel): xs: str +class StyleguideFontLinks(BaseModel): + files: Dict[str, str] + """Upright font files keyed by weight string (e.g. + + "400" for regular, "500", "700"). Values are absolute URLs. + """ + + type: Literal["google", "custom"] + + category: Optional[str] = None + """Google Fonts category when type is google (e.g. + + sans-serif, serif, monospace, display, handwriting). Omitted for custom fonts + when unknown. + """ + + display_name: Optional[str] = FieldInfo(alias="displayName", default=None) + """ + Present when type is custom: human-readable name derived from the fontLinks key + (strip build/hash suffixes, split camelCase / PascalCase, normalize separators). + Google entries omit this. + """ + + class StyleguideShadows(BaseModel): """Shadow styles used on the website""" @@ -371,6 +410,13 @@ class Styleguide(BaseModel): element_spacing: StyleguideElementSpacing = FieldInfo(alias="elementSpacing") """Spacing system used on the website""" + font_links: Dict[str, StyleguideFontLinks] = FieldInfo(alias="fontLinks") + """ + Font assets keyed by family name as it appears in fontFamily/fontFallbacks + (non-generic names only). Clients match typography.fontFamily / fontWeight or + button styles to pick a file URL from files. + """ + mode: Literal["light", "dark"] """The primary color mode of the website design""" @@ -388,6 +434,13 @@ class BrandStyleguideResponse(BaseModel): domain: Optional[str] = None """The normalized domain that was processed""" + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ + status: Optional[str] = None """Status of the response, e.g., 'ok'""" diff --git a/src/brand/dev/types/brand_web_scrape_html_params.py b/src/brand/dev/types/brand_web_scrape_html_params.py index 86246f42..657fdd09 100644 --- a/src/brand/dev/types/brand_web_scrape_html_params.py +++ b/src/brand/dev/types/brand_web_scrape_html_params.py @@ -2,11 +2,365 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing import Dict, Union, Iterable, Optional +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -__all__ = ["BrandWebScrapeHTMLParams"] +from .._types import SequenceNotStr +from .._utils import PropertyInfo + +__all__ = ["BrandWebScrapeHTMLParams", "Action", "ActionWebScrapeWaitAction", "ActionWebScrapePerformAction", "Pdf"] class BrandWebScrapeHTMLParams(TypedDict, total=False): url: Required[str] """Full URL to scrape (must include http:// or https:// protocol)""" + + actions: Optional[Iterable[Action]] + """ + Optional browser actions executed in array order after the page loads and before + content is captured. Requires a paid plan. Send a JSON array in the query + parameter. Maximum: 5 actions. + """ + + country: Literal[ + "ad", + "ae", + "af", + "ag", + "ai", + "al", + "am", + "ao", + "ar", + "at", + "au", + "aw", + "az", + "ba", + "bb", + "bd", + "be", + "bf", + "bg", + "bh", + "bi", + "bj", + "bm", + "bn", + "bo", + "bq", + "br", + "bs", + "bw", + "by", + "bz", + "ca", + "cd", + "cf", + "cg", + "ch", + "ci", + "cl", + "cm", + "cn", + "co", + "cr", + "cv", + "cw", + "cy", + "cz", + "de", + "dj", + "dk", + "dm", + "do", + "dz", + "ec", + "ee", + "eg", + "es", + "et", + "fi", + "fj", + "fr", + "ga", + "gb", + "gd", + "ge", + "gf", + "gg", + "gh", + "gm", + "gn", + "gp", + "gq", + "gr", + "gt", + "gu", + "gw", + "gy", + "hk", + "hn", + "hr", + "ht", + "hu", + "id", + "ie", + "il", + "im", + "in", + "iq", + "ir", + "is", + "it", + "je", + "jm", + "jo", + "jp", + "ke", + "kg", + "kh", + "kn", + "kr", + "kw", + "ky", + "kz", + "la", + "lb", + "lc", + "lk", + "lr", + "ls", + "lt", + "lu", + "lv", + "ly", + "ma", + "mc", + "md", + "me", + "mf", + "mg", + "mk", + "ml", + "mm", + "mn", + "mo", + "mq", + "mr", + "mt", + "mu", + "mv", + "mw", + "mx", + "my", + "mz", + "na", + "nc", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nz", + "om", + "pa", + "pe", + "pf", + "pg", + "ph", + "pk", + "pl", + "pr", + "ps", + "pt", + "py", + "qa", + "re", + "ro", + "rs", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sr", + "ss", + "st", + "sv", + "sx", + "sy", + "sz", + "tc", + "td", + "tg", + "th", + "tj", + "tl", + "tm", + "tn", + "tr", + "tt", + "tw", + "tz", + "ua", + "ug", + "us", + "uy", + "uz", + "vc", + "ve", + "vg", + "vi", + "vn", + "ye", + "yt", + "za", + "zm", + "zw", + ] + """ + Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). + """ + + exclude_selectors: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="excludeSelectors")] + """CSS selectors to remove from the result. + + Applied after includeSelectors. Exclusion takes precedence: an element matching + both is removed. Examples: "nav", "footer", ".ad-banner", "[aria-hidden=true]". + """ + + headers: Dict[str, str] + """ + Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. + """ + + include_frames: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="includeFrames")] + """When true, iframes are rendered inline into the returned HTML.""" + + include_selectors: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="includeSelectors")] + """CSS selectors. + + When provided, only matching subtrees (and their descendants) are kept and + everything else is dropped. When omitted, the entire document is kept. Examples: + "article.main", "#content", "[role=main]". + """ + + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """ + Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + """ + + pdf: Pdf + """PDF parsing controls. + + Use start/end to limit text extraction and embedded-image detection/OCR to an + inclusive 1-based page range. + """ + + settle_animations: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="settleAnimations")] + """ + When true, waits briefly for CSS and transition animations to settle before + extracting HTML. Defaults to false. This adds a bit of latency in exchange for + more stable output on animated pages. + """ + + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] + """Optional timeout in milliseconds for the request. + + If the request takes longer than this value, it will be aborted with a 408 + status code. Maximum allowed value is 300000ms (5 minutes). + """ + + use_main_content_only: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="useMainContentOnly")] + """ + When true, return only the page's main content in the HTML response, excluding + headers, footers, sidebars, and navigation when detectable. + """ + + wait_for_ms: Annotated[Optional[int], PropertyInfo(alias="waitForMs")] + """Optional browser wait time in milliseconds after initial page load. + + Min: 0. Max: 30000 (30 seconds). + """ + + zdr: Literal["enabled", "disabled"] + """ + Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. + """ + + +class ActionWebScrapeWaitAction(TypedDict, total=False): + """Pause for a fixed number of milliseconds before continuing to the next action.""" + + do: Required[Literal["wait"]] + + time_ms: Required[Annotated[int, PropertyInfo(alias="timeMs")]] + + +class ActionWebScrapePerformAction(TypedDict, total=False): + """Resolve and perform one natural-language browser action.""" + + action: Required[str] + + do: Required[Literal["perform"]] + + +Action: TypeAlias = Union[ActionWebScrapeWaitAction, ActionWebScrapePerformAction] + + +class Pdf(TypedDict, total=False): + """PDF parsing controls. + + Use start/end to limit text extraction and embedded-image detection/OCR to an inclusive 1-based page range. + """ + + end: int + """Last 1-based PDF page to parse. + + When omitted, parsing ends at the last page. Must be greater than or equal to + start when both are provided. + """ + + ocr: Union[bool, Literal["true", "false"]] + """ + When true, detect and OCR images embedded in the selected PDF pages, inserting + recognized text at each image's position in page reading order while preserving + the PDF text layer. This is separate from automatic scanned-PDF OCR fallback. + """ + + should_parse: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="shouldParse")] + """When true, PDF URLs are fetched and parsed. + + When false, PDF URLs are skipped and a 400 WEBSITE_ACCESS_ERROR is returned. + """ + + start: int + """First 1-based PDF page to parse. + + When omitted, parsing starts at the first page. + """ diff --git a/src/brand/dev/types/brand_web_scrape_html_response.py b/src/brand/dev/types/brand_web_scrape_html_response.py index a33cb79d..a4fe4ae0 100644 --- a/src/brand/dev/types/brand_web_scrape_html_response.py +++ b/src/brand/dev/types/brand_web_scrape_html_response.py @@ -1,18 +1,168 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from typing import Dict, List, Union, Optional from typing_extensions import Literal +from pydantic import Field as FieldInfo + from .._models import BaseModel -__all__ = ["BrandWebScrapeHTMLResponse"] +__all__ = ["BrandWebScrapeHTMLResponse", "Metadata", "MetadataAlternate", "ActionsApplied", "KeyMetadata"] + + +class MetadataAlternate(BaseModel): + href: str + """Resolved alternate URL.""" + + hreflang: Optional[str] = None + """Language or locale for the alternate URL, when present.""" + + title: Optional[str] = None + """Alternate resource title, when present.""" + + type: Optional[str] = None + """Alternate resource MIME type, when present.""" + + +class Metadata(BaseModel): + """Metadata extracted from the scraped page HTML.""" + + final_url: str = FieldInfo(alias="finalUrl") + """Final URL scraped after redirects or scraper fallback, when known. + + Falls back to sourceUrl when unavailable. + """ + + source_url: str = FieldInfo(alias="sourceUrl") + """Original URL requested by the caller.""" + + additional_meta: Optional[Dict[str, Union[str, List[str]]]] = FieldInfo(alias="additionalMeta", default=None) + """Additional non-social meta tags not promoted to top-level metadata fields.""" + + alternates: Optional[List[MetadataAlternate]] = None + """Resolved alternate links from link rel=alternate tags.""" + + author: Optional[str] = None + """Author metadata, when present.""" + + canonical_url: Optional[str] = FieldInfo(alias="canonicalUrl", default=None) + """Resolved canonical URL, when present.""" + + description: Optional[str] = None + """Best description extracted from standard, Open Graph, or Twitter metadata.""" + + favicon: Optional[str] = None + """Resolved favicon URL, when present.""" + + image: Optional[str] = None + """Primary resolved preview image from Open Graph, Twitter, or image metadata.""" + + json_ld: Optional[List[Dict[str, object]]] = FieldInfo(alias="jsonLd", default=None) + """JSON-LD structured data blocks parsed from the page.""" + + keywords: Optional[List[str]] = None + """Keywords extracted from the page's keywords meta tag.""" + + language: Optional[str] = None + """Language extracted from html lang or language meta tags.""" + + modified_time: Optional[str] = FieldInfo(alias="modifiedTime", default=None) + """Modified timestamp/date from page metadata, when present.""" + + open_graph: Optional[Dict[str, Union[str, List[str]]]] = FieldInfo(alias="openGraph", default=None) + """Open Graph metadata with the og: prefix removed and keys camel-cased.""" + + published_time: Optional[str] = FieldInfo(alias="publishedTime", default=None) + """Published timestamp/date from page metadata, when present.""" + + robots: Optional[str] = None + """Robots meta directive, when present.""" + + site_name: Optional[str] = FieldInfo(alias="siteName", default=None) + """Site or application name from page metadata.""" + + title: Optional[str] = None + """Best title extracted from the page.""" + + twitter: Optional[Dict[str, Union[str, List[str]]]] = None + """Twitter card metadata with the twitter: prefix removed and keys camel-cased.""" + + +class ActionsApplied(BaseModel): + instruction: str + + status: Literal["applied", "failed", "skipped"] + """Applied means the requested page state was visibly verified. + + Failed means it was not verified. Skipped means it was not attempted. + """ + + completion_evidence: Optional[str] = FieldInfo(alias="completionEvidence", default=None) + """Visible page evidence used to verify an applied action.""" + + duration_ms: Optional[float] = FieldInfo(alias="durationMs", default=None) + + error: Optional[str] = None + + method: Optional[str] = None + + target_description: Optional[str] = FieldInfo(alias="targetDescription", default=None) + + +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" class BrandWebScrapeHTMLResponse(BaseModel): html: str - """Raw HTML content of the page""" + """The scraped content of the page. + + For normal pages this is the raw HTML. When the page is a sitemap or feed served + behind an XSL stylesheet (which browsers render into HTML), this is the + underlying XML instead — see the `type` field. + """ + + metadata: Metadata + """Metadata extracted from the scraped page HTML.""" success: Literal[True] """Indicates success""" + type: Literal[ + "html", "xml", "json", "text", "csv", "markdown", "svg", "pdf", "docx", "doc", "xlsx", "xls", "pptx", "ppt" + ] + """Detected content type of the returned `html` field. + + Sitemaps and feeds are surfaced as `xml`; ordinary pages are `html`. Excel + workbooks are surfaced as `xlsx`/`xls` with the extracted sheets as HTML tables; + PowerPoint presentations are surfaced as `pptx`/`ppt` with the extracted slides + as HTML. + """ + url: str """The URL that was scraped""" + + actions_applied: Optional[List[ActionsApplied]] = FieldInfo(alias="actionsApplied", default=None) + """One verified outcome per requested browser action, in request order.""" + + actions_html_stale: Optional[bool] = FieldInfo(alias="actionsHtmlStale", default=None) + """ + True when an action was applied but the returned content could not be refreshed + afterward. + """ + + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ diff --git a/src/brand/dev/types/brand_web_scrape_images_params.py b/src/brand/dev/types/brand_web_scrape_images_params.py index 665c5f01..391e9d5e 100644 --- a/src/brand/dev/types/brand_web_scrape_images_params.py +++ b/src/brand/dev/types/brand_web_scrape_images_params.py @@ -2,11 +2,116 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing import Dict, Union, Iterable, Optional +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -__all__ = ["BrandWebScrapeImagesParams"] +from .._types import SequenceNotStr +from .._utils import PropertyInfo + +__all__ = [ + "BrandWebScrapeImagesParams", + "Action", + "ActionWebScrapeWaitAction", + "ActionWebScrapePerformAction", + "Enrichment", +] class BrandWebScrapeImagesParams(TypedDict, total=False): url: Required[str] - """Full URL to scrape images from (must include http:// or https:// protocol)""" + """Page URL to inspect. Must include http:// or https://.""" + + actions: Optional[Iterable[Action]] + """ + Optional browser actions executed in array order after the page loads and before + content is captured. Requires a paid plan. Send a JSON array in the query + parameter. Maximum: 5 actions. + """ + + dedupe: Union[bool, Literal["true", "false"]] + """ + When true, visually duplicate images are removed: every image is loaded and + perceptually hashed, and only the highest-resolution copy of each duplicate + group is kept. Images that cannot be downloaded or hashed are kept. Default: + false. + """ + + enrichment: Optional[Enrichment] + """ + Optional per-image processing, sent as deep-object query params such as + enrichment[resolution]=true. + """ + + headers: Dict[str, str] + """ + Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. + """ + + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """Reuse a cached result this many milliseconds old or newer. + + Default: 86400000 (1 day). Set to 0 to bypass cache. Maximum: 2592000000 (30 + days). + """ + + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] + """Optional timeout in milliseconds for the request. + + If the request takes longer than this value, it will be aborted with a 408 + status code. Maximum allowed value is 300000ms (5 minutes). + """ + + wait_for_ms: Annotated[Optional[int], PropertyInfo(alias="waitForMs")] + """ + Optional browser wait time in milliseconds after initial page load before + collecting images. Min: 0. Max: 30000 (30 seconds). + """ + + +class ActionWebScrapeWaitAction(TypedDict, total=False): + """Pause for a fixed number of milliseconds before continuing to the next action.""" + + do: Required[Literal["wait"]] + + time_ms: Required[Annotated[int, PropertyInfo(alias="timeMs")]] + + +class ActionWebScrapePerformAction(TypedDict, total=False): + """Resolve and perform one natural-language browser action.""" + + action: Required[str] + + do: Required[Literal["perform"]] + + +Action: TypeAlias = Union[ActionWebScrapeWaitAction, ActionWebScrapePerformAction] + + +class Enrichment(TypedDict, total=False): + """ + Optional per-image processing, sent as deep-object query params such as enrichment[resolution]=true. + """ + + classification: Union[bool, Literal["true", "false"]] + """Classify each image by visual asset type.""" + + hosted_url: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="hostedUrl")] + """ + Host materializable images on the Brand.dev CDN and return their URL and MIME + type. + """ + + max_time_per_ms: Annotated[int, PropertyInfo(alias="maxTimePerMs")] + """Per-image enrichment timeout in milliseconds. Default: 30000. Maximum: 60000.""" + + resolution: Union[bool, Literal["true", "false"]] + """Measure image width and height when possible.""" diff --git a/src/brand/dev/types/brand_web_scrape_images_response.py b/src/brand/dev/types/brand_web_scrape_images_response.py index 7f475f80..cbd0b8bb 100644 --- a/src/brand/dev/types/brand_web_scrape_images_response.py +++ b/src/brand/dev/types/brand_web_scrape_images_response.py @@ -5,29 +5,73 @@ from .._models import BaseModel -__all__ = ["BrandWebScrapeImagesResponse", "Image"] +__all__ = ["BrandWebScrapeImagesResponse", "Image", "ImageEnrichment", "KeyMetadata"] + + +class ImageEnrichment(BaseModel): + """Requested metadata for images that could be processed.""" + + height: Optional[int] = None + """Image height in pixels, when measured.""" + + mimetype: Optional[str] = None + """Detected MIME type, when hosted.""" + + type: Optional[ + Literal["photography", "illustration", "logo", "wordmark", "icon", "pattern", "graphic", "other"] + ] = None + """Visual asset category, when classified.""" + + url: Optional[str] = None + """Brand.dev CDN URL, when hosted.""" + + width: Optional[int] = None + """Image width in pixels, when measured.""" class Image(BaseModel): alt: Optional[str] = None - """Alt text of the image, or null if not present""" + """Image alt text, or null when unavailable.""" element: Literal["img", "svg", "link", "source", "video", "css", "object", "meta", "background"] - """The HTML element the image was found in""" + """Where the image was found.""" src: str - """The image source - can be a URL, inline HTML (for SVGs), or a base64 data URI""" + """Original image value: URL, inline SVG or HTML, or base64 data URI.""" type: Literal["url", "html", "base64"] - """The type/format of the src value""" + """Format of src.""" + + enrichment: Optional[ImageEnrichment] = None + """Requested metadata for images that could be processed.""" + + +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" class BrandWebScrapeImagesResponse(BaseModel): images: List[Image] - """Array of scraped images""" + """Images found on the page.""" success: Literal[True] - """Indicates success""" + """Always true on success.""" url: str - """The URL that was scraped""" + """Page URL that was scraped.""" + + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ diff --git a/src/brand/dev/types/brand_web_scrape_md_params.py b/src/brand/dev/types/brand_web_scrape_md_params.py index 6bf905eb..31093d48 100644 --- a/src/brand/dev/types/brand_web_scrape_md_params.py +++ b/src/brand/dev/types/brand_web_scrape_md_params.py @@ -2,31 +2,377 @@ from __future__ import annotations -from typing_extensions import Required, Annotated, TypedDict +from typing import Dict, Union, Iterable, Optional +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo -__all__ = ["BrandWebScrapeMdParams"] +__all__ = ["BrandWebScrapeMdParams", "Action", "ActionWebScrapeWaitAction", "ActionWebScrapePerformAction", "Pdf"] class BrandWebScrapeMdParams(TypedDict, total=False): url: Required[str] """ - Full URL to scrape and convert to markdown (must include http:// or https:// + Full URL to scrape into LLM usable Markdown (must include http:// or https:// protocol) """ - include_images: Annotated[bool, PropertyInfo(alias="includeImages")] + actions: Optional[Iterable[Action]] + """ + Optional browser actions executed in array order after the page loads and before + content is captured. Requires a paid plan. Send a JSON array in the query + parameter. Maximum: 5 actions. + """ + + country: Literal[ + "ad", + "ae", + "af", + "ag", + "ai", + "al", + "am", + "ao", + "ar", + "at", + "au", + "aw", + "az", + "ba", + "bb", + "bd", + "be", + "bf", + "bg", + "bh", + "bi", + "bj", + "bm", + "bn", + "bo", + "bq", + "br", + "bs", + "bw", + "by", + "bz", + "ca", + "cd", + "cf", + "cg", + "ch", + "ci", + "cl", + "cm", + "cn", + "co", + "cr", + "cv", + "cw", + "cy", + "cz", + "de", + "dj", + "dk", + "dm", + "do", + "dz", + "ec", + "ee", + "eg", + "es", + "et", + "fi", + "fj", + "fr", + "ga", + "gb", + "gd", + "ge", + "gf", + "gg", + "gh", + "gm", + "gn", + "gp", + "gq", + "gr", + "gt", + "gu", + "gw", + "gy", + "hk", + "hn", + "hr", + "ht", + "hu", + "id", + "ie", + "il", + "im", + "in", + "iq", + "ir", + "is", + "it", + "je", + "jm", + "jo", + "jp", + "ke", + "kg", + "kh", + "kn", + "kr", + "kw", + "ky", + "kz", + "la", + "lb", + "lc", + "lk", + "lr", + "ls", + "lt", + "lu", + "lv", + "ly", + "ma", + "mc", + "md", + "me", + "mf", + "mg", + "mk", + "ml", + "mm", + "mn", + "mo", + "mq", + "mr", + "mt", + "mu", + "mv", + "mw", + "mx", + "my", + "mz", + "na", + "nc", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nz", + "om", + "pa", + "pe", + "pf", + "pg", + "ph", + "pk", + "pl", + "pr", + "ps", + "pt", + "py", + "qa", + "re", + "ro", + "rs", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sr", + "ss", + "st", + "sv", + "sx", + "sy", + "sz", + "tc", + "td", + "tg", + "th", + "tj", + "tl", + "tm", + "tn", + "tr", + "tt", + "tw", + "tz", + "ua", + "ug", + "us", + "uy", + "uz", + "vc", + "ve", + "vg", + "vi", + "vn", + "ye", + "yt", + "za", + "zm", + "zw", + ] + """ + Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). + """ + + exclude_selectors: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="excludeSelectors")] + """CSS selectors to remove before conversion to Markdown. + + Applied after includeSelectors. Exclusion takes precedence: an element matching + both is removed. Examples: "nav", "footer", ".ad-banner", "[aria-hidden=true]". + """ + + headers: Dict[str, str] + """ + Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. + """ + + include_frames: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="includeFrames")] + """When true, the contents of iframes are rendered to Markdown.""" + + include_images: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="includeImages")] """Include image references in Markdown output""" - include_links: Annotated[bool, PropertyInfo(alias="includeLinks")] + include_links: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="includeLinks")] """Preserve hyperlinks in Markdown output""" - shorten_base64_images: Annotated[bool, PropertyInfo(alias="shortenBase64Images")] + include_selectors: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="includeSelectors")] + """CSS selectors. + + When provided, only matching HTML subtrees (and their descendants) are kept + before conversion to Markdown. When omitted, the entire document is kept. + Examples: "article.main", "#content", "[role=main]". + """ + + max_age_ms: Annotated[Optional[int], PropertyInfo(alias="maxAgeMs")] + """ + Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + """ + + pdf: Pdf + """PDF parsing controls. + + Use start/end to limit text extraction and embedded-image detection/OCR to an + inclusive 1-based page range. + """ + + settle_animations: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="settleAnimations")] + """ + When true, waits briefly for CSS and transition animations to settle before + converting to Markdown. Defaults to false. This adds a bit of latency in + exchange for more stable output on animated pages. + """ + + shorten_base64_images: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="shortenBase64Images")] """Shorten base64-encoded image data in the Markdown output""" - use_main_content_only: Annotated[bool, PropertyInfo(alias="useMainContentOnly")] + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] + """Optional timeout in milliseconds for the request. + + If the request takes longer than this value, it will be aborted with a 408 + status code. Maximum allowed value is 300000ms (5 minutes). + """ + + use_main_content_only: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="useMainContentOnly")] """ Extract only the main content of the page, excluding headers, footers, sidebars, and navigation """ + + wait_for_ms: Annotated[Optional[int], PropertyInfo(alias="waitForMs")] + """ + Optional browser wait time in milliseconds after initial page load before + converting the page to Markdown. Min: 0. Max: 30000 (30 seconds). + """ + + zdr: Literal["enabled", "disabled"] + """ + Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. + """ + + +class ActionWebScrapeWaitAction(TypedDict, total=False): + """Pause for a fixed number of milliseconds before continuing to the next action.""" + + do: Required[Literal["wait"]] + + time_ms: Required[Annotated[int, PropertyInfo(alias="timeMs")]] + + +class ActionWebScrapePerformAction(TypedDict, total=False): + """Resolve and perform one natural-language browser action.""" + + action: Required[str] + + do: Required[Literal["perform"]] + + +Action: TypeAlias = Union[ActionWebScrapeWaitAction, ActionWebScrapePerformAction] + + +class Pdf(TypedDict, total=False): + """PDF parsing controls. + + Use start/end to limit text extraction and embedded-image detection/OCR to an inclusive 1-based page range. + """ + + end: int + """Last 1-based PDF page to parse. + + When omitted, parsing ends at the last page. Must be greater than or equal to + start when both are provided. + """ + + ocr: Union[bool, Literal["true", "false"]] + """ + When true, detect and OCR images embedded in the selected PDF pages, inserting + recognized text at each image's position in page reading order while preserving + the PDF text layer. This is separate from automatic scanned-PDF OCR fallback. + """ + + should_parse: Annotated[Union[bool, Literal["true", "false"]], PropertyInfo(alias="shouldParse")] + """When true, PDF URLs are fetched and parsed. + + When false, PDF URLs are skipped and a 400 WEBSITE_ACCESS_ERROR is returned. + """ + + start: int + """First 1-based PDF page to parse. + + When omitted, parsing starts at the first page. + """ diff --git a/src/brand/dev/types/brand_web_scrape_md_response.py b/src/brand/dev/types/brand_web_scrape_md_response.py index 51612434..9cd18cd1 100644 --- a/src/brand/dev/types/brand_web_scrape_md_response.py +++ b/src/brand/dev/types/brand_web_scrape_md_response.py @@ -1,18 +1,159 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from typing import Dict, List, Union, Optional from typing_extensions import Literal +from pydantic import Field as FieldInfo + from .._models import BaseModel -__all__ = ["BrandWebScrapeMdResponse"] +__all__ = ["BrandWebScrapeMdResponse", "Metadata", "MetadataAlternate", "ActionsApplied", "KeyMetadata"] + + +class MetadataAlternate(BaseModel): + href: str + """Resolved alternate URL.""" + + hreflang: Optional[str] = None + """Language or locale for the alternate URL, when present.""" + + title: Optional[str] = None + """Alternate resource title, when present.""" + + type: Optional[str] = None + """Alternate resource MIME type, when present.""" + + +class Metadata(BaseModel): + """Metadata extracted from the scraped page HTML.""" + + final_url: str = FieldInfo(alias="finalUrl") + """Final URL scraped after redirects or scraper fallback, when known. + + Falls back to sourceUrl when unavailable. + """ + + source_url: str = FieldInfo(alias="sourceUrl") + """Original URL requested by the caller.""" + + additional_meta: Optional[Dict[str, Union[str, List[str]]]] = FieldInfo(alias="additionalMeta", default=None) + """Additional non-social meta tags not promoted to top-level metadata fields.""" + + alternates: Optional[List[MetadataAlternate]] = None + """Resolved alternate links from link rel=alternate tags.""" + + author: Optional[str] = None + """Author metadata, when present.""" + + canonical_url: Optional[str] = FieldInfo(alias="canonicalUrl", default=None) + """Resolved canonical URL, when present.""" + + description: Optional[str] = None + """Best description extracted from standard, Open Graph, or Twitter metadata.""" + + favicon: Optional[str] = None + """Resolved favicon URL, when present.""" + + image: Optional[str] = None + """Primary resolved preview image from Open Graph, Twitter, or image metadata.""" + + json_ld: Optional[List[Dict[str, object]]] = FieldInfo(alias="jsonLd", default=None) + """JSON-LD structured data blocks parsed from the page.""" + + keywords: Optional[List[str]] = None + """Keywords extracted from the page's keywords meta tag.""" + + language: Optional[str] = None + """Language extracted from html lang or language meta tags.""" + + modified_time: Optional[str] = FieldInfo(alias="modifiedTime", default=None) + """Modified timestamp/date from page metadata, when present.""" + + open_graph: Optional[Dict[str, Union[str, List[str]]]] = FieldInfo(alias="openGraph", default=None) + """Open Graph metadata with the og: prefix removed and keys camel-cased.""" + + published_time: Optional[str] = FieldInfo(alias="publishedTime", default=None) + """Published timestamp/date from page metadata, when present.""" + + robots: Optional[str] = None + """Robots meta directive, when present.""" + + site_name: Optional[str] = FieldInfo(alias="siteName", default=None) + """Site or application name from page metadata.""" + + title: Optional[str] = None + """Best title extracted from the page.""" + + twitter: Optional[Dict[str, Union[str, List[str]]]] = None + """Twitter card metadata with the twitter: prefix removed and keys camel-cased.""" + + +class ActionsApplied(BaseModel): + instruction: str + + status: Literal["applied", "failed", "skipped"] + """Applied means the requested page state was visibly verified. + + Failed means it was not verified. Skipped means it was not attempted. + """ + + completion_evidence: Optional[str] = FieldInfo(alias="completionEvidence", default=None) + """Visible page evidence used to verify an applied action.""" + + duration_ms: Optional[float] = FieldInfo(alias="durationMs", default=None) + + error: Optional[str] = None + + method: Optional[str] = None + + target_description: Optional[str] = FieldInfo(alias="targetDescription", default=None) + + +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" class BrandWebScrapeMdResponse(BaseModel): + content_length: int = FieldInfo(alias="contentLength") + """UTF-8 byte length of the returned Markdown. + + Use 0 to identify an empty result and compare small values against your + workload's minimum useful-content threshold. + """ + markdown: str """Page content converted to GitHub Flavored Markdown""" + metadata: Metadata + """Metadata extracted from the scraped page HTML.""" + success: Literal[True] """Indicates success""" url: str """The URL that was scraped""" + + actions_applied: Optional[List[ActionsApplied]] = FieldInfo(alias="actionsApplied", default=None) + """One verified outcome per requested browser action, in request order.""" + + actions_html_stale: Optional[bool] = FieldInfo(alias="actionsHtmlStale", default=None) + """ + True when an action was applied but the returned content could not be refreshed + afterward. + """ + + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ diff --git a/src/brand/dev/types/brand_web_scrape_sitemap_params.py b/src/brand/dev/types/brand_web_scrape_sitemap_params.py index e675dae3..d052eae4 100644 --- a/src/brand/dev/types/brand_web_scrape_sitemap_params.py +++ b/src/brand/dev/types/brand_web_scrape_sitemap_params.py @@ -2,8 +2,10 @@ from __future__ import annotations -from typing_extensions import Required, Annotated, TypedDict +from typing import Dict +from typing_extensions import Literal, Required, Annotated, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo __all__ = ["BrandWebScrapeSitemapParams"] @@ -11,9 +13,13 @@ class BrandWebScrapeSitemapParams(TypedDict, total=False): domain: Required[str] - """Domain name to crawl sitemaps for (e.g., 'example.com'). + """Domain to build a sitemap for""" - The domain will be automatically normalized and validated. + headers: Dict[str, str] + """ + Optional outbound HTTP headers forwarded only to the target URL, sent as + deep-object query params such as headers[X-Custom]=value. When provided, caching + is bypassed: the result is neither read from nor written to cache. """ max_links: Annotated[int, PropertyInfo(alias="maxLinks")] @@ -21,3 +27,38 @@ class BrandWebScrapeSitemapParams(TypedDict, total=False): Defaults to 10,000. Minimum is 1, maximum is 100,000. """ + + sitemap_url: Annotated[str, PropertyInfo(alias="sitemapUrl")] + """Optional explicit sitemap URL. + + When provided, exactly this sitemap is crawled instead of discovering the + domain's sitemaps. + """ + + tags: SequenceNotStr[str] + """Optional comma-separated caller-defined tags for tracking this request. + + Tags are recorded on the request's usage log and can be used to filter usage on + the dashboard usage page. Up to 20 tags, each 1-50 characters. + """ + + timeout_ms: Annotated[int, PropertyInfo(alias="timeoutMS")] + """Optional timeout in milliseconds for the request. + + If the request takes longer than this value, it will be aborted with a 408 + status code. Maximum allowed value is 300000ms (5 minutes). + """ + + url_regex: Annotated[str, PropertyInfo(alias="urlRegex")] + """Optional RE2-compatible regex pattern. + + Only URLs matching this pattern are returned and counted against maxLinks. + """ + + zdr: Literal["enabled", "disabled"] + """ + Set to enabled to bypass shared caches and omit request and response content + from retained usage logs. Requires zero data retention to be enabled for your + organization (contact support@context.dev), otherwise the request fails with + ZDR_NOT_ENABLED. Successful ZDR responses include X-Context-ZDR: true. + """ diff --git a/src/brand/dev/types/brand_web_scrape_sitemap_response.py b/src/brand/dev/types/brand_web_scrape_sitemap_response.py index ae7562e3..b5489f65 100644 --- a/src/brand/dev/types/brand_web_scrape_sitemap_response.py +++ b/src/brand/dev/types/brand_web_scrape_sitemap_response.py @@ -1,13 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List +from typing import List, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo from .._models import BaseModel -__all__ = ["BrandWebScrapeSitemapResponse", "Meta"] +__all__ = ["BrandWebScrapeSitemapResponse", "Meta", "KeyMetadata"] class Meta(BaseModel): @@ -26,6 +26,19 @@ class Meta(BaseModel): """Number of sitemap files skipped (due to errors, timeouts, or limits)""" +class KeyMetadata(BaseModel): + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the response status is not 200. + """ + + credits_consumed: int + """The number of credits consumed by this request.""" + + credits_remaining: int + """The number of credits remaining for your organization after this request.""" + + class BrandWebScrapeSitemapResponse(BaseModel): domain: str """The normalized domain that was crawled""" @@ -38,3 +51,10 @@ class BrandWebScrapeSitemapResponse(BaseModel): urls: List[str] """Array of discovered page URLs from the sitemap (max 500)""" + + key_metadata: Optional[KeyMetadata] = None + """Metadata about the API key used for the request. + + Included in every response whenever a valid API key is provided, even when the + response status is not 200. + """ diff --git a/tests/api_resources/test_brand.py b/tests/api_resources/test_brand.py index 55875859..511ac8aa 100644 --- a/tests/api_resources/test_brand.py +++ b/tests/api_resources/test_brand.py @@ -41,18 +41,21 @@ class TestBrand: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_retrieve(self, client: BrandDev) -> None: - brand = client.brand.retrieve( - domain="domain", - ) + brand = client.brand.retrieve() assert_matches_type(BrandRetrieveResponse, brand, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_retrieve_with_all_params(self, client: BrandDev) -> None: brand = client.brand.retrieve( - domain="domain", - force_language="albanian", - max_speed=True, + domain="xxx", + force_language="afrikaans", + max_age_ms=0, + max_speed="true", + name="xxx", + tags=["production", "team-alpha"], + ticker="ticker", + ticker_exchange="AMEX", timeout_ms=1000, ) assert_matches_type(BrandRetrieveResponse, brand, path=["response"]) @@ -60,9 +63,7 @@ def test_method_retrieve_with_all_params(self, client: BrandDev) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_retrieve(self, client: BrandDev) -> None: - response = client.brand.with_raw_response.retrieve( - domain="domain", - ) + response = client.brand.with_raw_response.retrieve() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -72,9 +73,7 @@ def test_raw_response_retrieve(self, client: BrandDev) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_retrieve(self, client: BrandDev) -> None: - with client.brand.with_streaming_response.retrieve( - domain="domain", - ) as response: + with client.brand.with_streaming_response.retrieve() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -96,6 +95,8 @@ def test_method_ai_product(self, client: BrandDev) -> None: def test_method_ai_product_with_all_params(self, client: BrandDev) -> None: brand = client.brand.ai_product( url="https://example.com", + max_age_ms=0, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandAIProductResponse, brand, path=["response"]) @@ -139,7 +140,9 @@ def test_method_ai_products_overload_1(self, client: BrandDev) -> None: def test_method_ai_products_with_all_params_overload_1(self, client: BrandDev) -> None: brand = client.brand.ai_products( domain="domain", + max_age_ms=0, max_products=1, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandAIProductsResponse, brand, path=["response"]) @@ -183,7 +186,9 @@ def test_method_ai_products_overload_2(self, client: BrandDev) -> None: def test_method_ai_products_with_all_params_overload_2(self, client: BrandDev) -> None: brand = client.brand.ai_products( direct_url="https://example.com", + max_age_ms=0, max_products=1, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandAIProductsResponse, brand, path=["response"]) @@ -259,6 +264,7 @@ def test_method_ai_query_with_all_params(self, client: BrandDev) -> None: "privacy_policy": True, "terms_and_conditions": True, }, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandAIQueryResponse, brand, path=["response"]) @@ -308,16 +314,17 @@ def test_streaming_response_ai_query(self, client: BrandDev) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_fonts(self, client: BrandDev) -> None: - brand = client.brand.fonts( - domain="domain", - ) + brand = client.brand.fonts() assert_matches_type(BrandFontsResponse, brand, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_fonts_with_all_params(self, client: BrandDev) -> None: brand = client.brand.fonts( - domain="domain", + direct_url="https://example.com", + domain="xxx", + max_age_ms=0, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandFontsResponse, brand, path=["response"]) @@ -325,9 +332,7 @@ def test_method_fonts_with_all_params(self, client: BrandDev) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_fonts(self, client: BrandDev) -> None: - response = client.brand.with_raw_response.fonts( - domain="domain", - ) + response = client.brand.with_raw_response.fonts() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -337,9 +342,7 @@ def test_raw_response_fonts(self, client: BrandDev) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_fonts(self, client: BrandDev) -> None: - with client.brand.with_streaming_response.fonts( - domain="domain", - ) as response: + with client.brand.with_streaming_response.fonts() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -352,7 +355,7 @@ def test_streaming_response_fonts(self, client: BrandDev) -> None: @parametrize def test_method_identify_from_transaction(self, client: BrandDev) -> None: brand = client.brand.identify_from_transaction( - transaction_info="transaction_info", + transaction_info="xxx", ) assert_matches_type(BrandIdentifyFromTransactionResponse, brand, path=["response"]) @@ -360,14 +363,15 @@ def test_method_identify_from_transaction(self, client: BrandDev) -> None: @parametrize def test_method_identify_from_transaction_with_all_params(self, client: BrandDev) -> None: brand = client.brand.identify_from_transaction( - transaction_info="transaction_info", + transaction_info="xxx", city="city", - country_gl="ad", - force_language="albanian", - high_confidence_only=True, - max_speed=True, - mcc="mcc", - phone=0, + country_gl="af", + force_language="afrikaans", + high_confidence_only="true", + max_speed="true", + mcc="string", + phone="string", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandIdentifyFromTransactionResponse, brand, path=["response"]) @@ -376,7 +380,7 @@ def test_method_identify_from_transaction_with_all_params(self, client: BrandDev @parametrize def test_raw_response_identify_from_transaction(self, client: BrandDev) -> None: response = client.brand.with_raw_response.identify_from_transaction( - transaction_info="transaction_info", + transaction_info="xxx", ) assert response.is_closed is True @@ -388,7 +392,7 @@ def test_raw_response_identify_from_transaction(self, client: BrandDev) -> None: @parametrize def test_streaming_response_identify_from_transaction(self, client: BrandDev) -> None: with client.brand.with_streaming_response.identify_from_transaction( - transaction_info="transaction_info", + transaction_info="xxx", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -411,6 +415,7 @@ def test_method_prefetch(self, client: BrandDev) -> None: def test_method_prefetch_with_all_params(self, client: BrandDev) -> None: brand = client.brand.prefetch( domain="domain", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandPrefetchResponse, brand, path=["response"]) @@ -454,6 +459,7 @@ def test_method_prefetch_by_email(self, client: BrandDev) -> None: def test_method_prefetch_by_email_with_all_params(self, client: BrandDev) -> None: brand = client.brand.prefetch_by_email( email="dev@stainless.com", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandPrefetchByEmailResponse, brand, path=["response"]) @@ -497,8 +503,10 @@ def test_method_retrieve_by_email(self, client: BrandDev) -> None: def test_method_retrieve_by_email_with_all_params(self, client: BrandDev) -> None: brand = client.brand.retrieve_by_email( email="dev@stainless.com", - force_language="albanian", - max_speed=True, + force_language="afrikaans", + max_age_ms=0, + max_speed="true", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandRetrieveByEmailResponse, brand, path=["response"]) @@ -542,8 +550,10 @@ def test_method_retrieve_by_isin(self, client: BrandDev) -> None: def test_method_retrieve_by_isin_with_all_params(self, client: BrandDev) -> None: brand = client.brand.retrieve_by_isin( isin="SE60513A9993", - force_language="albanian", - max_speed=True, + force_language="afrikaans", + max_age_ms=0, + max_speed="true", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandRetrieveByIsinResponse, brand, path=["response"]) @@ -587,9 +597,11 @@ def test_method_retrieve_by_name(self, client: BrandDev) -> None: def test_method_retrieve_by_name_with_all_params(self, client: BrandDev) -> None: brand = client.brand.retrieve_by_name( name="xxx", - country_gl="ad", - force_language="albanian", - max_speed=True, + country_gl="af", + force_language="afrikaans", + max_age_ms=0, + max_speed="true", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandRetrieveByNameResponse, brand, path=["response"]) @@ -633,8 +645,10 @@ def test_method_retrieve_by_ticker(self, client: BrandDev) -> None: def test_method_retrieve_by_ticker_with_all_params(self, client: BrandDev) -> None: brand = client.brand.retrieve_by_ticker( ticker="ticker", - force_language="albanian", - max_speed=True, + force_language="afrikaans", + max_age_ms=0, + max_speed="true", + tags=["production", "team-alpha"], ticker_exchange="AMEX", timeout_ms=1000, ) @@ -670,7 +684,7 @@ def test_streaming_response_retrieve_by_ticker(self, client: BrandDev) -> None: @parametrize def test_method_retrieve_naics(self, client: BrandDev) -> None: brand = client.brand.retrieve_naics( - input="input", + input="xxxx", ) assert_matches_type(BrandRetrieveNaicsResponse, brand, path=["response"]) @@ -678,9 +692,10 @@ def test_method_retrieve_naics(self, client: BrandDev) -> None: @parametrize def test_method_retrieve_naics_with_all_params(self, client: BrandDev) -> None: brand = client.brand.retrieve_naics( - input="input", + input="xxxx", max_results=1, min_results=1, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandRetrieveNaicsResponse, brand, path=["response"]) @@ -689,7 +704,7 @@ def test_method_retrieve_naics_with_all_params(self, client: BrandDev) -> None: @parametrize def test_raw_response_retrieve_naics(self, client: BrandDev) -> None: response = client.brand.with_raw_response.retrieve_naics( - input="input", + input="xxxx", ) assert response.is_closed is True @@ -701,7 +716,7 @@ def test_raw_response_retrieve_naics(self, client: BrandDev) -> None: @parametrize def test_streaming_response_retrieve_naics(self, client: BrandDev) -> None: with client.brand.with_streaming_response.retrieve_naics( - input="input", + input="xxxx", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -715,7 +730,7 @@ def test_streaming_response_retrieve_naics(self, client: BrandDev) -> None: @parametrize def test_method_retrieve_simplified(self, client: BrandDev) -> None: brand = client.brand.retrieve_simplified( - domain="domain", + domain="xxx", ) assert_matches_type(BrandRetrieveSimplifiedResponse, brand, path=["response"]) @@ -723,7 +738,10 @@ def test_method_retrieve_simplified(self, client: BrandDev) -> None: @parametrize def test_method_retrieve_simplified_with_all_params(self, client: BrandDev) -> None: brand = client.brand.retrieve_simplified( - domain="domain", + domain="xxx", + max_age_ms=0, + tags=["production", "team-alpha"], + theme="light", timeout_ms=1000, ) assert_matches_type(BrandRetrieveSimplifiedResponse, brand, path=["response"]) @@ -732,7 +750,7 @@ def test_method_retrieve_simplified_with_all_params(self, client: BrandDev) -> N @parametrize def test_raw_response_retrieve_simplified(self, client: BrandDev) -> None: response = client.brand.with_raw_response.retrieve_simplified( - domain="domain", + domain="xxx", ) assert response.is_closed is True @@ -744,7 +762,7 @@ def test_raw_response_retrieve_simplified(self, client: BrandDev) -> None: @parametrize def test_streaming_response_retrieve_simplified(self, client: BrandDev) -> None: with client.brand.with_streaming_response.retrieve_simplified( - domain="domain", + domain="xxx", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -757,28 +775,37 @@ def test_streaming_response_retrieve_simplified(self, client: BrandDev) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_screenshot(self, client: BrandDev) -> None: - brand = client.brand.screenshot( - domain="domain", - ) + brand = client.brand.screenshot() assert_matches_type(BrandScreenshotResponse, brand, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_screenshot_with_all_params(self, client: BrandDev) -> None: brand = client.brand.screenshot( - domain="domain", + color_scheme="light", + country="de", + direct_url="https://example.com", + domain="xxx", full_screenshot="true", + handle_cookie_popup="true", + max_age_ms=0, page="login", - prioritize="speed", + scroll_offset=0, + tags=["production", "team-alpha"], + timeout_ms=1, + viewport={ + "height": 240, + "width": 240, + }, + wait_for_ms=0, + zdr="enabled", ) assert_matches_type(BrandScreenshotResponse, brand, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_screenshot(self, client: BrandDev) -> None: - response = client.brand.with_raw_response.screenshot( - domain="domain", - ) + response = client.brand.with_raw_response.screenshot() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -788,9 +815,7 @@ def test_raw_response_screenshot(self, client: BrandDev) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_screenshot(self, client: BrandDev) -> None: - with client.brand.with_streaming_response.screenshot( - domain="domain", - ) as response: + with client.brand.with_streaming_response.screenshot() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -809,8 +834,11 @@ def test_method_styleguide(self, client: BrandDev) -> None: @parametrize def test_method_styleguide_with_all_params(self, client: BrandDev) -> None: brand = client.brand.styleguide( + color_scheme="light", direct_url="https://example.com", - domain="domain", + domain="xxx", + max_age_ms=0, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandStyleguideResponse, brand, path=["response"]) @@ -845,6 +873,38 @@ def test_method_web_scrape_html(self, client: BrandDev) -> None: ) assert_matches_type(BrandWebScrapeHTMLResponse, brand, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_web_scrape_html_with_all_params(self, client: BrandDev) -> None: + brand = client.brand.web_scrape_html( + url="https://example.com", + actions=[ + { + "do": "wait", + "time_ms": 0, + } + ], + country="de", + exclude_selectors=["x"], + headers={"foo": "J!"}, + include_frames="true", + include_selectors=["x"], + max_age_ms=0, + pdf={ + "end": 1, + "ocr": "true", + "should_parse": "true", + "start": 1, + }, + settle_animations="true", + tags=["production", "team-alpha"], + timeout_ms=1, + use_main_content_only="true", + wait_for_ms=0, + zdr="enabled", + ) + assert_matches_type(BrandWebScrapeHTMLResponse, brand, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_web_scrape_html(self, client: BrandDev) -> None: @@ -879,6 +939,32 @@ def test_method_web_scrape_images(self, client: BrandDev) -> None: ) assert_matches_type(BrandWebScrapeImagesResponse, brand, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_web_scrape_images_with_all_params(self, client: BrandDev) -> None: + brand = client.brand.web_scrape_images( + url="https://example.com", + actions=[ + { + "do": "wait", + "time_ms": 0, + } + ], + dedupe="true", + enrichment={ + "classification": "true", + "hosted_url": "true", + "max_time_per_ms": 1, + "resolution": "true", + }, + headers={"foo": "J!"}, + max_age_ms=0, + tags=["production", "team-alpha"], + timeout_ms=1, + wait_for_ms=0, + ) + assert_matches_type(BrandWebScrapeImagesResponse, brand, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_web_scrape_images(self, client: BrandDev) -> None: @@ -918,10 +1004,33 @@ def test_method_web_scrape_md(self, client: BrandDev) -> None: def test_method_web_scrape_md_with_all_params(self, client: BrandDev) -> None: brand = client.brand.web_scrape_md( url="https://example.com", - include_images=True, - include_links=True, - shorten_base64_images=True, - use_main_content_only=True, + actions=[ + { + "do": "wait", + "time_ms": 0, + } + ], + country="de", + exclude_selectors=["x"], + headers={"foo": "J!"}, + include_frames="true", + include_images="true", + include_links="true", + include_selectors=["x"], + max_age_ms=0, + pdf={ + "end": 1, + "ocr": "true", + "should_parse": "true", + "start": 1, + }, + settle_animations="true", + shorten_base64_images="true", + tags=["production", "team-alpha"], + timeout_ms=1, + use_main_content_only="true", + wait_for_ms=0, + zdr="enabled", ) assert_matches_type(BrandWebScrapeMdResponse, brand, path=["response"]) @@ -955,7 +1064,7 @@ def test_streaming_response_web_scrape_md(self, client: BrandDev) -> None: @parametrize def test_method_web_scrape_sitemap(self, client: BrandDev) -> None: brand = client.brand.web_scrape_sitemap( - domain="domain", + domain="xxx", ) assert_matches_type(BrandWebScrapeSitemapResponse, brand, path=["response"]) @@ -963,8 +1072,14 @@ def test_method_web_scrape_sitemap(self, client: BrandDev) -> None: @parametrize def test_method_web_scrape_sitemap_with_all_params(self, client: BrandDev) -> None: brand = client.brand.web_scrape_sitemap( - domain="domain", + domain="xxx", + headers={"foo": "J!"}, max_links=1, + sitemap_url="https://example.com", + tags=["production", "team-alpha"], + timeout_ms=1, + url_regex="^https?://[^/]+/blog/", + zdr="enabled", ) assert_matches_type(BrandWebScrapeSitemapResponse, brand, path=["response"]) @@ -972,7 +1087,7 @@ def test_method_web_scrape_sitemap_with_all_params(self, client: BrandDev) -> No @parametrize def test_raw_response_web_scrape_sitemap(self, client: BrandDev) -> None: response = client.brand.with_raw_response.web_scrape_sitemap( - domain="domain", + domain="xxx", ) assert response.is_closed is True @@ -984,7 +1099,7 @@ def test_raw_response_web_scrape_sitemap(self, client: BrandDev) -> None: @parametrize def test_streaming_response_web_scrape_sitemap(self, client: BrandDev) -> None: with client.brand.with_streaming_response.web_scrape_sitemap( - domain="domain", + domain="xxx", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1003,18 +1118,21 @@ class TestAsyncBrand: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_retrieve(self, async_client: AsyncBrandDev) -> None: - brand = await async_client.brand.retrieve( - domain="domain", - ) + brand = await async_client.brand.retrieve() assert_matches_type(BrandRetrieveResponse, brand, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_retrieve_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.retrieve( - domain="domain", - force_language="albanian", - max_speed=True, + domain="xxx", + force_language="afrikaans", + max_age_ms=0, + max_speed="true", + name="xxx", + tags=["production", "team-alpha"], + ticker="ticker", + ticker_exchange="AMEX", timeout_ms=1000, ) assert_matches_type(BrandRetrieveResponse, brand, path=["response"]) @@ -1022,9 +1140,7 @@ async def test_method_retrieve_with_all_params(self, async_client: AsyncBrandDev @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_retrieve(self, async_client: AsyncBrandDev) -> None: - response = await async_client.brand.with_raw_response.retrieve( - domain="domain", - ) + response = await async_client.brand.with_raw_response.retrieve() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1034,9 +1150,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncBrandDev) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncBrandDev) -> None: - async with async_client.brand.with_streaming_response.retrieve( - domain="domain", - ) as response: + async with async_client.brand.with_streaming_response.retrieve() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1058,6 +1172,8 @@ async def test_method_ai_product(self, async_client: AsyncBrandDev) -> None: async def test_method_ai_product_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.ai_product( url="https://example.com", + max_age_ms=0, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandAIProductResponse, brand, path=["response"]) @@ -1101,7 +1217,9 @@ async def test_method_ai_products_overload_1(self, async_client: AsyncBrandDev) async def test_method_ai_products_with_all_params_overload_1(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.ai_products( domain="domain", + max_age_ms=0, max_products=1, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandAIProductsResponse, brand, path=["response"]) @@ -1145,7 +1263,9 @@ async def test_method_ai_products_overload_2(self, async_client: AsyncBrandDev) async def test_method_ai_products_with_all_params_overload_2(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.ai_products( direct_url="https://example.com", + max_age_ms=0, max_products=1, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandAIProductsResponse, brand, path=["response"]) @@ -1221,6 +1341,7 @@ async def test_method_ai_query_with_all_params(self, async_client: AsyncBrandDev "privacy_policy": True, "terms_and_conditions": True, }, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandAIQueryResponse, brand, path=["response"]) @@ -1270,16 +1391,17 @@ async def test_streaming_response_ai_query(self, async_client: AsyncBrandDev) -> @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_fonts(self, async_client: AsyncBrandDev) -> None: - brand = await async_client.brand.fonts( - domain="domain", - ) + brand = await async_client.brand.fonts() assert_matches_type(BrandFontsResponse, brand, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_fonts_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.fonts( - domain="domain", + direct_url="https://example.com", + domain="xxx", + max_age_ms=0, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandFontsResponse, brand, path=["response"]) @@ -1287,9 +1409,7 @@ async def test_method_fonts_with_all_params(self, async_client: AsyncBrandDev) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_fonts(self, async_client: AsyncBrandDev) -> None: - response = await async_client.brand.with_raw_response.fonts( - domain="domain", - ) + response = await async_client.brand.with_raw_response.fonts() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1299,9 +1419,7 @@ async def test_raw_response_fonts(self, async_client: AsyncBrandDev) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_fonts(self, async_client: AsyncBrandDev) -> None: - async with async_client.brand.with_streaming_response.fonts( - domain="domain", - ) as response: + async with async_client.brand.with_streaming_response.fonts() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1314,7 +1432,7 @@ async def test_streaming_response_fonts(self, async_client: AsyncBrandDev) -> No @parametrize async def test_method_identify_from_transaction(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.identify_from_transaction( - transaction_info="transaction_info", + transaction_info="xxx", ) assert_matches_type(BrandIdentifyFromTransactionResponse, brand, path=["response"]) @@ -1322,14 +1440,15 @@ async def test_method_identify_from_transaction(self, async_client: AsyncBrandDe @parametrize async def test_method_identify_from_transaction_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.identify_from_transaction( - transaction_info="transaction_info", + transaction_info="xxx", city="city", - country_gl="ad", - force_language="albanian", - high_confidence_only=True, - max_speed=True, - mcc="mcc", - phone=0, + country_gl="af", + force_language="afrikaans", + high_confidence_only="true", + max_speed="true", + mcc="string", + phone="string", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandIdentifyFromTransactionResponse, brand, path=["response"]) @@ -1338,7 +1457,7 @@ async def test_method_identify_from_transaction_with_all_params(self, async_clie @parametrize async def test_raw_response_identify_from_transaction(self, async_client: AsyncBrandDev) -> None: response = await async_client.brand.with_raw_response.identify_from_transaction( - transaction_info="transaction_info", + transaction_info="xxx", ) assert response.is_closed is True @@ -1350,7 +1469,7 @@ async def test_raw_response_identify_from_transaction(self, async_client: AsyncB @parametrize async def test_streaming_response_identify_from_transaction(self, async_client: AsyncBrandDev) -> None: async with async_client.brand.with_streaming_response.identify_from_transaction( - transaction_info="transaction_info", + transaction_info="xxx", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1373,6 +1492,7 @@ async def test_method_prefetch(self, async_client: AsyncBrandDev) -> None: async def test_method_prefetch_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.prefetch( domain="domain", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandPrefetchResponse, brand, path=["response"]) @@ -1416,6 +1536,7 @@ async def test_method_prefetch_by_email(self, async_client: AsyncBrandDev) -> No async def test_method_prefetch_by_email_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.prefetch_by_email( email="dev@stainless.com", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandPrefetchByEmailResponse, brand, path=["response"]) @@ -1459,8 +1580,10 @@ async def test_method_retrieve_by_email(self, async_client: AsyncBrandDev) -> No async def test_method_retrieve_by_email_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.retrieve_by_email( email="dev@stainless.com", - force_language="albanian", - max_speed=True, + force_language="afrikaans", + max_age_ms=0, + max_speed="true", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandRetrieveByEmailResponse, brand, path=["response"]) @@ -1504,8 +1627,10 @@ async def test_method_retrieve_by_isin(self, async_client: AsyncBrandDev) -> Non async def test_method_retrieve_by_isin_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.retrieve_by_isin( isin="SE60513A9993", - force_language="albanian", - max_speed=True, + force_language="afrikaans", + max_age_ms=0, + max_speed="true", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandRetrieveByIsinResponse, brand, path=["response"]) @@ -1549,9 +1674,11 @@ async def test_method_retrieve_by_name(self, async_client: AsyncBrandDev) -> Non async def test_method_retrieve_by_name_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.retrieve_by_name( name="xxx", - country_gl="ad", - force_language="albanian", - max_speed=True, + country_gl="af", + force_language="afrikaans", + max_age_ms=0, + max_speed="true", + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandRetrieveByNameResponse, brand, path=["response"]) @@ -1595,8 +1722,10 @@ async def test_method_retrieve_by_ticker(self, async_client: AsyncBrandDev) -> N async def test_method_retrieve_by_ticker_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.retrieve_by_ticker( ticker="ticker", - force_language="albanian", - max_speed=True, + force_language="afrikaans", + max_age_ms=0, + max_speed="true", + tags=["production", "team-alpha"], ticker_exchange="AMEX", timeout_ms=1000, ) @@ -1632,7 +1761,7 @@ async def test_streaming_response_retrieve_by_ticker(self, async_client: AsyncBr @parametrize async def test_method_retrieve_naics(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.retrieve_naics( - input="input", + input="xxxx", ) assert_matches_type(BrandRetrieveNaicsResponse, brand, path=["response"]) @@ -1640,9 +1769,10 @@ async def test_method_retrieve_naics(self, async_client: AsyncBrandDev) -> None: @parametrize async def test_method_retrieve_naics_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.retrieve_naics( - input="input", + input="xxxx", max_results=1, min_results=1, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandRetrieveNaicsResponse, brand, path=["response"]) @@ -1651,7 +1781,7 @@ async def test_method_retrieve_naics_with_all_params(self, async_client: AsyncBr @parametrize async def test_raw_response_retrieve_naics(self, async_client: AsyncBrandDev) -> None: response = await async_client.brand.with_raw_response.retrieve_naics( - input="input", + input="xxxx", ) assert response.is_closed is True @@ -1663,7 +1793,7 @@ async def test_raw_response_retrieve_naics(self, async_client: AsyncBrandDev) -> @parametrize async def test_streaming_response_retrieve_naics(self, async_client: AsyncBrandDev) -> None: async with async_client.brand.with_streaming_response.retrieve_naics( - input="input", + input="xxxx", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1677,7 +1807,7 @@ async def test_streaming_response_retrieve_naics(self, async_client: AsyncBrandD @parametrize async def test_method_retrieve_simplified(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.retrieve_simplified( - domain="domain", + domain="xxx", ) assert_matches_type(BrandRetrieveSimplifiedResponse, brand, path=["response"]) @@ -1685,7 +1815,10 @@ async def test_method_retrieve_simplified(self, async_client: AsyncBrandDev) -> @parametrize async def test_method_retrieve_simplified_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.retrieve_simplified( - domain="domain", + domain="xxx", + max_age_ms=0, + tags=["production", "team-alpha"], + theme="light", timeout_ms=1000, ) assert_matches_type(BrandRetrieveSimplifiedResponse, brand, path=["response"]) @@ -1694,7 +1827,7 @@ async def test_method_retrieve_simplified_with_all_params(self, async_client: As @parametrize async def test_raw_response_retrieve_simplified(self, async_client: AsyncBrandDev) -> None: response = await async_client.brand.with_raw_response.retrieve_simplified( - domain="domain", + domain="xxx", ) assert response.is_closed is True @@ -1706,7 +1839,7 @@ async def test_raw_response_retrieve_simplified(self, async_client: AsyncBrandDe @parametrize async def test_streaming_response_retrieve_simplified(self, async_client: AsyncBrandDev) -> None: async with async_client.brand.with_streaming_response.retrieve_simplified( - domain="domain", + domain="xxx", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1719,28 +1852,37 @@ async def test_streaming_response_retrieve_simplified(self, async_client: AsyncB @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_screenshot(self, async_client: AsyncBrandDev) -> None: - brand = await async_client.brand.screenshot( - domain="domain", - ) + brand = await async_client.brand.screenshot() assert_matches_type(BrandScreenshotResponse, brand, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_screenshot_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.screenshot( - domain="domain", + color_scheme="light", + country="de", + direct_url="https://example.com", + domain="xxx", full_screenshot="true", + handle_cookie_popup="true", + max_age_ms=0, page="login", - prioritize="speed", + scroll_offset=0, + tags=["production", "team-alpha"], + timeout_ms=1, + viewport={ + "height": 240, + "width": 240, + }, + wait_for_ms=0, + zdr="enabled", ) assert_matches_type(BrandScreenshotResponse, brand, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_screenshot(self, async_client: AsyncBrandDev) -> None: - response = await async_client.brand.with_raw_response.screenshot( - domain="domain", - ) + response = await async_client.brand.with_raw_response.screenshot() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1750,9 +1892,7 @@ async def test_raw_response_screenshot(self, async_client: AsyncBrandDev) -> Non @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_screenshot(self, async_client: AsyncBrandDev) -> None: - async with async_client.brand.with_streaming_response.screenshot( - domain="domain", - ) as response: + async with async_client.brand.with_streaming_response.screenshot() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1771,8 +1911,11 @@ async def test_method_styleguide(self, async_client: AsyncBrandDev) -> None: @parametrize async def test_method_styleguide_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.styleguide( + color_scheme="light", direct_url="https://example.com", - domain="domain", + domain="xxx", + max_age_ms=0, + tags=["production", "team-alpha"], timeout_ms=1000, ) assert_matches_type(BrandStyleguideResponse, brand, path=["response"]) @@ -1807,6 +1950,38 @@ async def test_method_web_scrape_html(self, async_client: AsyncBrandDev) -> None ) assert_matches_type(BrandWebScrapeHTMLResponse, brand, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_web_scrape_html_with_all_params(self, async_client: AsyncBrandDev) -> None: + brand = await async_client.brand.web_scrape_html( + url="https://example.com", + actions=[ + { + "do": "wait", + "time_ms": 0, + } + ], + country="de", + exclude_selectors=["x"], + headers={"foo": "J!"}, + include_frames="true", + include_selectors=["x"], + max_age_ms=0, + pdf={ + "end": 1, + "ocr": "true", + "should_parse": "true", + "start": 1, + }, + settle_animations="true", + tags=["production", "team-alpha"], + timeout_ms=1, + use_main_content_only="true", + wait_for_ms=0, + zdr="enabled", + ) + assert_matches_type(BrandWebScrapeHTMLResponse, brand, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_web_scrape_html(self, async_client: AsyncBrandDev) -> None: @@ -1841,6 +2016,32 @@ async def test_method_web_scrape_images(self, async_client: AsyncBrandDev) -> No ) assert_matches_type(BrandWebScrapeImagesResponse, brand, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_web_scrape_images_with_all_params(self, async_client: AsyncBrandDev) -> None: + brand = await async_client.brand.web_scrape_images( + url="https://example.com", + actions=[ + { + "do": "wait", + "time_ms": 0, + } + ], + dedupe="true", + enrichment={ + "classification": "true", + "hosted_url": "true", + "max_time_per_ms": 1, + "resolution": "true", + }, + headers={"foo": "J!"}, + max_age_ms=0, + tags=["production", "team-alpha"], + timeout_ms=1, + wait_for_ms=0, + ) + assert_matches_type(BrandWebScrapeImagesResponse, brand, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_web_scrape_images(self, async_client: AsyncBrandDev) -> None: @@ -1880,10 +2081,33 @@ async def test_method_web_scrape_md(self, async_client: AsyncBrandDev) -> None: async def test_method_web_scrape_md_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.web_scrape_md( url="https://example.com", - include_images=True, - include_links=True, - shorten_base64_images=True, - use_main_content_only=True, + actions=[ + { + "do": "wait", + "time_ms": 0, + } + ], + country="de", + exclude_selectors=["x"], + headers={"foo": "J!"}, + include_frames="true", + include_images="true", + include_links="true", + include_selectors=["x"], + max_age_ms=0, + pdf={ + "end": 1, + "ocr": "true", + "should_parse": "true", + "start": 1, + }, + settle_animations="true", + shorten_base64_images="true", + tags=["production", "team-alpha"], + timeout_ms=1, + use_main_content_only="true", + wait_for_ms=0, + zdr="enabled", ) assert_matches_type(BrandWebScrapeMdResponse, brand, path=["response"]) @@ -1917,7 +2141,7 @@ async def test_streaming_response_web_scrape_md(self, async_client: AsyncBrandDe @parametrize async def test_method_web_scrape_sitemap(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.web_scrape_sitemap( - domain="domain", + domain="xxx", ) assert_matches_type(BrandWebScrapeSitemapResponse, brand, path=["response"]) @@ -1925,8 +2149,14 @@ async def test_method_web_scrape_sitemap(self, async_client: AsyncBrandDev) -> N @parametrize async def test_method_web_scrape_sitemap_with_all_params(self, async_client: AsyncBrandDev) -> None: brand = await async_client.brand.web_scrape_sitemap( - domain="domain", + domain="xxx", + headers={"foo": "J!"}, max_links=1, + sitemap_url="https://example.com", + tags=["production", "team-alpha"], + timeout_ms=1, + url_regex="^https?://[^/]+/blog/", + zdr="enabled", ) assert_matches_type(BrandWebScrapeSitemapResponse, brand, path=["response"]) @@ -1934,7 +2164,7 @@ async def test_method_web_scrape_sitemap_with_all_params(self, async_client: Asy @parametrize async def test_raw_response_web_scrape_sitemap(self, async_client: AsyncBrandDev) -> None: response = await async_client.brand.with_raw_response.web_scrape_sitemap( - domain="domain", + domain="xxx", ) assert response.is_closed is True @@ -1946,7 +2176,7 @@ async def test_raw_response_web_scrape_sitemap(self, async_client: AsyncBrandDev @parametrize async def test_streaming_response_web_scrape_sitemap(self, async_client: AsyncBrandDev) -> None: async with async_client.brand.with_streaming_response.web_scrape_sitemap( - domain="domain", + domain="xxx", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/test_client.py b/tests/test_client.py index 9a1bb3de..0fdc3dd9 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -429,6 +429,30 @@ def test_default_query_option(self) -> None: client.close() + def test_hardcoded_query_params_in_url(self, client: BrandDev) -> 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: BrandDev) -> None: request = client._build_request( FinalRequestOptions( @@ -854,7 +878,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien respx_mock.get("/brand/retrieve").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - client.brand.with_streaming_response.retrieve(domain="domain").__enter__() + client.brand.with_streaming_response.retrieve().__enter__() assert _get_open_connections(client) == 0 @@ -864,7 +888,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client respx_mock.get("/brand/retrieve").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - client.brand.with_streaming_response.retrieve(domain="domain").__enter__() + client.brand.with_streaming_response.retrieve().__enter__() assert _get_open_connections(client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @@ -893,7 +917,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.get("/brand/retrieve").mock(side_effect=retry_handler) - response = client.brand.with_raw_response.retrieve(domain="domain") + response = client.brand.with_raw_response.retrieve() assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -917,9 +941,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.get("/brand/retrieve").mock(side_effect=retry_handler) - response = client.brand.with_raw_response.retrieve( - domain="domain", extra_headers={"x-stainless-retry-count": Omit()} - ) + response = client.brand.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": Omit()}) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -942,9 +964,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.get("/brand/retrieve").mock(side_effect=retry_handler) - response = client.brand.with_raw_response.retrieve( - domain="domain", extra_headers={"x-stainless-retry-count": "42"} - ) + response = client.brand.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": "42"}) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1324,6 +1344,30 @@ async def test_default_query_option(self) -> None: await client.close() + async def test_hardcoded_query_params_in_url(self, async_client: AsyncBrandDev) -> 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: BrandDev) -> None: request = client._build_request( FinalRequestOptions( @@ -1766,7 +1810,7 @@ async def test_retrying_timeout_errors_doesnt_leak( respx_mock.get("/brand/retrieve").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - await async_client.brand.with_streaming_response.retrieve(domain="domain").__aenter__() + await async_client.brand.with_streaming_response.retrieve().__aenter__() assert _get_open_connections(async_client) == 0 @@ -1778,7 +1822,7 @@ async def test_retrying_status_errors_doesnt_leak( respx_mock.get("/brand/retrieve").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - await async_client.brand.with_streaming_response.retrieve(domain="domain").__aenter__() + await async_client.brand.with_streaming_response.retrieve().__aenter__() assert _get_open_connections(async_client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @@ -1807,7 +1851,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.get("/brand/retrieve").mock(side_effect=retry_handler) - response = await client.brand.with_raw_response.retrieve(domain="domain") + response = await client.brand.with_raw_response.retrieve() assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -1831,9 +1875,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.get("/brand/retrieve").mock(side_effect=retry_handler) - response = await client.brand.with_raw_response.retrieve( - domain="domain", extra_headers={"x-stainless-retry-count": Omit()} - ) + response = await client.brand.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": Omit()}) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -1856,9 +1898,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.get("/brand/retrieve").mock(side_effect=retry_handler) - response = await client.brand.with_raw_response.retrieve( - domain="domain", extra_headers={"x-stainless-retry-count": "42"} - ) + response = await client.brand.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": "42"}) assert response.http_request.headers.get("x-stainless-retry-count") == "42" diff --git a/tests/test_deepcopy.py b/tests/test_deepcopy.py deleted file mode 100644 index 937bf726..00000000 --- a/tests/test_deepcopy.py +++ /dev/null @@ -1,58 +0,0 @@ -from brand.dev._utils import deepcopy_minimal - - -def assert_different_identities(obj1: object, obj2: object) -> None: - assert obj1 == obj2 - assert id(obj1) != id(obj2) - - -def test_simple_dict() -> None: - obj1 = {"foo": "bar"} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - - -def test_nested_dict() -> None: - obj1 = {"foo": {"bar": True}} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1["foo"], obj2["foo"]) - - -def test_complex_nested_dict() -> None: - obj1 = {"foo": {"bar": [{"hello": "world"}]}} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1["foo"], obj2["foo"]) - assert_different_identities(obj1["foo"]["bar"], obj2["foo"]["bar"]) - assert_different_identities(obj1["foo"]["bar"][0], obj2["foo"]["bar"][0]) - - -def test_simple_list() -> None: - obj1 = ["a", "b", "c"] - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - - -def test_nested_list() -> None: - obj1 = ["a", [1, 2, 3]] - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1[1], obj2[1]) - - -class MyObject: ... - - -def test_ignores_other_types() -> None: - # custom classes - my_obj = MyObject() - obj1 = {"foo": my_obj} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert obj1["foo"] is my_obj - - # tuples - obj3 = ("a", "b") - obj4 = deepcopy_minimal(obj3) - assert obj3 is obj4 diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index 72d0a8b6..ba150ec3 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -4,7 +4,7 @@ import pytest -from brand.dev._types import FileTypes +from brand.dev._types import FileTypes, ArrayFormat from brand.dev._utils import extract_files @@ -35,6 +35,12 @@ def test_multiple_files() -> None: assert query == {"documents": [{}, {}]} +def test_top_level_file_array() -> None: + query = {"files": [b"file one", b"file two"], "title": "hello"} + assert extract_files(query, paths=[["files", ""]]) == [("files[]", b"file one"), ("files[]", b"file two")] + assert query == {"title": "hello"} + + @pytest.mark.parametrize( "query,paths,expected", [ @@ -62,3 +68,24 @@ def test_ignores_incorrect_paths( expected: list[tuple[str, FileTypes]], ) -> None: assert extract_files(query, paths=paths) == expected + + +@pytest.mark.parametrize( + "array_format,expected_top_level,expected_nested", + [ + ("brackets", [("files[]", b"a"), ("files[]", b"b")], [("items[][file]", b"a"), ("items[][file]", b"b")]), + ("repeat", [("files", b"a"), ("files", b"b")], [("items[file]", b"a"), ("items[file]", b"b")]), + ("comma", [("files", b"a"), ("files", b"b")], [("items[file]", b"a"), ("items[file]", b"b")]), + ("indices", [("files[0]", b"a"), ("files[1]", b"b")], [("items[0][file]", b"a"), ("items[1][file]", b"b")]), + ], +) +def test_array_format_controls_file_field_names( + array_format: ArrayFormat, + expected_top_level: list[tuple[str, FileTypes]], + expected_nested: list[tuple[str, FileTypes]], +) -> None: + top_level = {"files": [b"a", b"b"]} + assert extract_files(top_level, paths=[["files", ""]], array_format=array_format) == expected_top_level + + nested = {"items": [{"file": b"a"}, {"file": b"b"}]} + assert extract_files(nested, paths=[["items", "", "file"]], array_format=array_format) == expected_nested diff --git a/tests/test_files.py b/tests/test_files.py index 9af98b86..62632e10 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -4,7 +4,8 @@ import pytest from dirty_equals import IsDict, IsList, IsBytes, IsTuple -from brand.dev._files import to_httpx_files, async_to_httpx_files +from brand.dev._files import to_httpx_files, deepcopy_with_paths, async_to_httpx_files +from brand.dev._utils import extract_files readme_path = Path(__file__).parent.parent.joinpath("README.md") @@ -49,3 +50,99 @@ def test_string_not_allowed() -> None: "file": "foo", # type: ignore } ) + + +def assert_different_identities(obj1: object, obj2: object) -> None: + assert obj1 == obj2 + assert obj1 is not obj2 + + +class TestDeepcopyWithPaths: + def test_copies_top_level_dict(self) -> None: + original = {"file": b"data", "other": "value"} + result = deepcopy_with_paths(original, [["file"]]) + assert_different_identities(result, original) + + def test_file_value_is_same_reference(self) -> None: + file_bytes = b"contents" + original = {"file": file_bytes} + result = deepcopy_with_paths(original, [["file"]]) + assert_different_identities(result, original) + assert result["file"] is file_bytes + + def test_list_popped_wholesale(self) -> None: + files = [b"f1", b"f2"] + original = {"files": files, "title": "t"} + result = deepcopy_with_paths(original, [["files", ""]]) + assert_different_identities(result, original) + result_files = result["files"] + assert isinstance(result_files, list) + assert_different_identities(result_files, files) + + def test_nested_array_path_copies_list_and_elements(self) -> None: + elem1 = {"file": b"f1", "extra": 1} + elem2 = {"file": b"f2", "extra": 2} + original = {"items": [elem1, elem2]} + result = deepcopy_with_paths(original, [["items", "", "file"]]) + assert_different_identities(result, original) + result_items = result["items"] + assert isinstance(result_items, list) + assert_different_identities(result_items, original["items"]) + assert_different_identities(result_items[0], elem1) + assert_different_identities(result_items[1], elem2) + + def test_empty_paths_returns_same_object(self) -> None: + original = {"foo": "bar"} + result = deepcopy_with_paths(original, []) + assert result is original + + def test_multiple_paths(self) -> None: + f1 = b"file1" + f2 = b"file2" + original = {"a": f1, "b": f2, "c": "unchanged"} + result = deepcopy_with_paths(original, [["a"], ["b"]]) + assert_different_identities(result, original) + assert result["a"] is f1 + assert result["b"] is f2 + assert result["c"] is original["c"] + + def test_extract_files_does_not_mutate_original_top_level(self) -> None: + file_bytes = b"contents" + original = {"file": file_bytes, "other": "value"} + + copied = deepcopy_with_paths(original, [["file"]]) + extracted = extract_files(copied, paths=[["file"]]) + + assert extracted == [("file", file_bytes)] + assert original == {"file": file_bytes, "other": "value"} + assert copied == {"other": "value"} + + def test_extract_files_does_not_mutate_original_nested_array_path(self) -> None: + file1 = b"f1" + file2 = b"f2" + original = { + "items": [ + {"file": file1, "extra": 1}, + {"file": file2, "extra": 2}, + ], + "title": "example", + } + + copied = deepcopy_with_paths(original, [["items", "", "file"]]) + extracted = extract_files(copied, paths=[["items", "", "file"]]) + + assert [entry for _, entry in extracted] == [file1, file2] + assert original == { + "items": [ + {"file": file1, "extra": 1}, + {"file": file2, "extra": 2}, + ], + "title": "example", + } + assert copied == { + "items": [ + {"extra": 1}, + {"extra": 2}, + ], + "title": "example", + } diff --git a/tests/test_models.py b/tests/test_models.py index 66e35654..8e9ab3a7 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,7 +1,8 @@ import json -from typing import TYPE_CHECKING, Any, Dict, List, Union, Optional, cast +from typing import TYPE_CHECKING, Any, Dict, List, Union, Iterable, Optional, cast from datetime import datetime, timezone -from typing_extensions import Literal, Annotated, TypeAliasType +from collections import deque +from typing_extensions import Literal, Annotated, TypedDict, TypeAliasType import pytest import pydantic @@ -9,7 +10,7 @@ from brand.dev._utils import PropertyInfo from brand.dev._compat import PYDANTIC_V1, parse_obj, model_dump, model_json -from brand.dev._models import DISCRIMINATOR_CACHE, BaseModel, construct_type +from brand.dev._models import DISCRIMINATOR_CACHE, BaseModel, EagerIterable, construct_type class BasicModel(BaseModel): @@ -961,3 +962,56 @@ def __getattr__(self, attr: str) -> Item: ... assert model.a.prop == 1 assert isinstance(model.a, Item) assert model.other == "foo" + + +# NOTE: Workaround for Pydantic Iterable behavior. +# Iterable fields are replaced with a ValidatorIterator and may be consumed +# during serialization, which can cause subsequent dumps to return empty data. +# See: https://github.com/pydantic/pydantic/issues/9541 +@pytest.mark.parametrize( + "data, expected_validated", + [ + ([1, 2, 3], [1, 2, 3]), + ((1, 2, 3), (1, 2, 3)), + (set([1, 2, 3]), set([1, 2, 3])), + (iter([1, 2, 3]), [1, 2, 3]), + ([], []), + ((x for x in [1, 2, 3]), [1, 2, 3]), + (map(lambda x: x, [1, 2, 3]), [1, 2, 3]), + (frozenset([1, 2, 3]), frozenset([1, 2, 3])), + (deque([1, 2, 3]), deque([1, 2, 3])), + ], + ids=["list", "tuple", "set", "iterator", "empty", "generator", "map", "frozenset", "deque"], +) +@pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2") +def test_iterable_construction(data: Iterable[int], expected_validated: Iterable[int]) -> None: + class TypeWithIterable(TypedDict): + items: EagerIterable[int] + + class Model(BaseModel): + data: TypeWithIterable + + m = Model.model_validate({"data": {"items": data}}) + assert m.data["items"] == expected_validated + + # Verify repeated dumps don't lose data (the original bug) + assert m.model_dump()["data"]["items"] == list(expected_validated) + assert m.model_dump()["data"]["items"] == list(expected_validated) + + +@pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2") +def test_iterable_construction_str_falls_back_to_list() -> None: + # str is iterable (over chars), but str(list_of_chars) produces the list's repr + # rather than reconstructing a string from items. We special-case str to fall + # back to list instead of attempting reconstruction. + class TypeWithIterable(TypedDict): + items: EagerIterable[str] + + class Model(BaseModel): + data: TypeWithIterable + + m = Model.model_validate({"data": {"items": "hello"}}) + + # falls back to list of chars rather than calling str(["h", "e", "l", "l", "o"]) + assert m.data["items"] == ["h", "e", "l", "l", "o"] + assert m.model_dump()["data"]["items"] == ["h", "e", "l", "l", "o"]