diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index e72f1131..7ccfe12c 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "1.14.0"
+ ".": "1.15.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index b4d46dde..1ac83c1a 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 36
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/browserbase-e82c289d3d3aabd936a476cf81630587ffe46ab9e9bdebced4b31b8c2f9bc08f.yml
-openapi_spec_hash: 473121b283812a3dfd866afe9b61dc7d
-config_hash: 1b24ea9fa13645b16b74aa794dbc8190
+configured_endpoints: 38
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase/browserbase-98cc68ad9afa71355baf2b31f305a5e2f3a315fd311c96659405eff96b8f2b1e.yml
+openapi_spec_hash: 71dfbc1021a33dd7fc9d82844965b1b3
+config_hash: 6209a285dd5980f5c418fe6575723aef
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7b1cbfc1..76e15c3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 1.15.0 (2026-07-14)
+
+Full Changelog: [v1.14.0...v1.15.0](https://github.com/browserbase/sdk-python/compare/v1.14.0...v1.15.0)
+
+### Features
+
+* **api:** manual updates ([39fee02](https://github.com/browserbase/sdk-python/commit/39fee028ec9f64b472dcbe2cac94f044bed79a4b))
+
## 1.14.0 (2026-07-02)
Full Changelog: [v1.13.0...v1.14.0](https://github.com/browserbase/sdk-python/compare/v1.13.0...v1.14.0)
diff --git a/api.md b/api.md
index 39c108f5..8e9c89ba 100644
--- a/api.md
+++ b/api.md
@@ -130,7 +130,24 @@ from browserbase.types.sessions import SessionRecording, RecordingRetrieveRespon
Methods:
-- client.sessions.recording.retrieve(id) -> RecordingRetrieveResponse
+- client.sessions.recording.retrieve(id) -> RecordingRetrieveResponse
+
+### Downloads
+
+Types:
+
+```python
+from browserbase.types.sessions.recording import (
+ RecordingDownload,
+ DownloadCreateResponse,
+ DownloadListResponse,
+)
+```
+
+Methods:
+
+- client.sessions.recording.downloads.create(id) -> DownloadCreateResponse
+- client.sessions.recording.downloads.list(id) -> DownloadListResponse
## Uploads
diff --git a/pyproject.toml b/pyproject.toml
index 542ff757..86985708 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "browserbase"
-version = "1.14.0"
+version = "1.15.0"
description = "The official Python library for the Browserbase API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/browserbase/_version.py b/src/browserbase/_version.py
index 4df49f49..cb52e162 100644
--- a/src/browserbase/_version.py
+++ b/src/browserbase/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "browserbase"
-__version__ = "1.14.0" # x-release-please-version
+__version__ = "1.15.0" # x-release-please-version
diff --git a/src/browserbase/resources/sessions/recording/__init__.py b/src/browserbase/resources/sessions/recording/__init__.py
new file mode 100644
index 00000000..99f9205b
--- /dev/null
+++ b/src/browserbase/resources/sessions/recording/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .downloads import (
+ DownloadsResource,
+ AsyncDownloadsResource,
+ DownloadsResourceWithRawResponse,
+ AsyncDownloadsResourceWithRawResponse,
+ DownloadsResourceWithStreamingResponse,
+ AsyncDownloadsResourceWithStreamingResponse,
+)
+from .recording import (
+ RecordingResource,
+ AsyncRecordingResource,
+ RecordingResourceWithRawResponse,
+ AsyncRecordingResourceWithRawResponse,
+ RecordingResourceWithStreamingResponse,
+ AsyncRecordingResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "DownloadsResource",
+ "AsyncDownloadsResource",
+ "DownloadsResourceWithRawResponse",
+ "AsyncDownloadsResourceWithRawResponse",
+ "DownloadsResourceWithStreamingResponse",
+ "AsyncDownloadsResourceWithStreamingResponse",
+ "RecordingResource",
+ "AsyncRecordingResource",
+ "RecordingResourceWithRawResponse",
+ "AsyncRecordingResourceWithRawResponse",
+ "RecordingResourceWithStreamingResponse",
+ "AsyncRecordingResourceWithStreamingResponse",
+]
diff --git a/src/browserbase/resources/sessions/recording/downloads.py b/src/browserbase/resources/sessions/recording/downloads.py
new file mode 100644
index 00000000..04cd51bb
--- /dev/null
+++ b/src/browserbase/resources/sessions/recording/downloads.py
@@ -0,0 +1,253 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from ...._types import Body, Query, Headers, NotGiven, not_given
+from ...._utils import path_template
+from ...._compat import cached_property
+from ...._resource import SyncAPIResource, AsyncAPIResource
+from ...._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...._base_client import make_request_options
+from ....types.sessions.recording.download_list_response import DownloadListResponse
+from ....types.sessions.recording.download_create_response import DownloadCreateResponse
+
+__all__ = ["DownloadsResource", "AsyncDownloadsResource"]
+
+
+class DownloadsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> DownloadsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/browserbase/sdk-python#accessing-raw-response-data-eg-headers
+ """
+ return DownloadsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> DownloadsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/browserbase/sdk-python#with_streaming_response
+ """
+ return DownloadsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> DownloadCreateResponse:
+ """Requests one downloadable MP4 per recorded page of a session.
+
+ Assembly runs
+ asynchronously and every page returns as `PENDING`. Re-posting re-enqueues all
+ pages and retries any that failed. Poll the GET endpoint for per-page status
+ and, on standard (non-BYOS) projects, download URLs.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._post(
+ path_template("/v1/sessions/{id}/recording/downloads", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=DownloadCreateResponse,
+ )
+
+ def list(
+ self,
+ id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> DownloadListResponse:
+ """
+ Returns the per-page download status for a session, with a short-lived signed
+ URL for each completed page on standard (non-BYOS) projects.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._get(
+ path_template("/v1/sessions/{id}/recording/downloads", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=DownloadListResponse,
+ )
+
+
+class AsyncDownloadsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncDownloadsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/browserbase/sdk-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncDownloadsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncDownloadsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/browserbase/sdk-python#with_streaming_response
+ """
+ return AsyncDownloadsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> DownloadCreateResponse:
+ """Requests one downloadable MP4 per recorded page of a session.
+
+ Assembly runs
+ asynchronously and every page returns as `PENDING`. Re-posting re-enqueues all
+ pages and retries any that failed. Poll the GET endpoint for per-page status
+ and, on standard (non-BYOS) projects, download URLs.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._post(
+ path_template("/v1/sessions/{id}/recording/downloads", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=DownloadCreateResponse,
+ )
+
+ async def list(
+ self,
+ id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> DownloadListResponse:
+ """
+ Returns the per-page download status for a session, with a short-lived signed
+ URL for each completed page on standard (non-BYOS) projects.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._get(
+ path_template("/v1/sessions/{id}/recording/downloads", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=DownloadListResponse,
+ )
+
+
+class DownloadsResourceWithRawResponse:
+ def __init__(self, downloads: DownloadsResource) -> None:
+ self._downloads = downloads
+
+ self.create = to_raw_response_wrapper(
+ downloads.create,
+ )
+ self.list = to_raw_response_wrapper(
+ downloads.list,
+ )
+
+
+class AsyncDownloadsResourceWithRawResponse:
+ def __init__(self, downloads: AsyncDownloadsResource) -> None:
+ self._downloads = downloads
+
+ self.create = async_to_raw_response_wrapper(
+ downloads.create,
+ )
+ self.list = async_to_raw_response_wrapper(
+ downloads.list,
+ )
+
+
+class DownloadsResourceWithStreamingResponse:
+ def __init__(self, downloads: DownloadsResource) -> None:
+ self._downloads = downloads
+
+ self.create = to_streamed_response_wrapper(
+ downloads.create,
+ )
+ self.list = to_streamed_response_wrapper(
+ downloads.list,
+ )
+
+
+class AsyncDownloadsResourceWithStreamingResponse:
+ def __init__(self, downloads: AsyncDownloadsResource) -> None:
+ self._downloads = downloads
+
+ self.create = async_to_streamed_response_wrapper(
+ downloads.create,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ downloads.list,
+ )
diff --git a/src/browserbase/resources/sessions/recording.py b/src/browserbase/resources/sessions/recording/recording.py
similarity index 78%
rename from src/browserbase/resources/sessions/recording.py
rename to src/browserbase/resources/sessions/recording/recording.py
index 57e2d44e..18394e0d 100644
--- a/src/browserbase/resources/sessions/recording.py
+++ b/src/browserbase/resources/sessions/recording/recording.py
@@ -4,23 +4,35 @@
import httpx
-from ..._types import Body, Query, Headers, NotGiven, not_given
-from ..._utils import path_template
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
+from ...._types import Body, Query, Headers, NotGiven, not_given
+from ...._utils import path_template
+from .downloads import (
+ DownloadsResource,
+ AsyncDownloadsResource,
+ DownloadsResourceWithRawResponse,
+ AsyncDownloadsResourceWithRawResponse,
+ DownloadsResourceWithStreamingResponse,
+ AsyncDownloadsResourceWithStreamingResponse,
+)
+from ...._compat import cached_property
+from ...._resource import SyncAPIResource, AsyncAPIResource
+from ...._response import (
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ..._base_client import make_request_options
-from ...types.sessions.recording_retrieve_response import RecordingRetrieveResponse
+from ...._base_client import make_request_options
+from ....types.sessions.recording_retrieve_response import RecordingRetrieveResponse
__all__ = ["RecordingResource", "AsyncRecordingResource"]
class RecordingResource(SyncAPIResource):
+ @cached_property
+ def downloads(self) -> DownloadsResource:
+ return DownloadsResource(self._client)
+
@cached_property
def with_raw_response(self) -> RecordingResourceWithRawResponse:
"""
@@ -75,6 +87,10 @@ def retrieve(
class AsyncRecordingResource(AsyncAPIResource):
+ @cached_property
+ def downloads(self) -> AsyncDownloadsResource:
+ return AsyncDownloadsResource(self._client)
+
@cached_property
def with_raw_response(self) -> AsyncRecordingResourceWithRawResponse:
"""
@@ -136,6 +152,10 @@ def __init__(self, recording: RecordingResource) -> None:
recording.retrieve,
)
+ @cached_property
+ def downloads(self) -> DownloadsResourceWithRawResponse:
+ return DownloadsResourceWithRawResponse(self._recording.downloads)
+
class AsyncRecordingResourceWithRawResponse:
def __init__(self, recording: AsyncRecordingResource) -> None:
@@ -145,6 +165,10 @@ def __init__(self, recording: AsyncRecordingResource) -> None:
recording.retrieve,
)
+ @cached_property
+ def downloads(self) -> AsyncDownloadsResourceWithRawResponse:
+ return AsyncDownloadsResourceWithRawResponse(self._recording.downloads)
+
class RecordingResourceWithStreamingResponse:
def __init__(self, recording: RecordingResource) -> None:
@@ -154,6 +178,10 @@ def __init__(self, recording: RecordingResource) -> None:
recording.retrieve,
)
+ @cached_property
+ def downloads(self) -> DownloadsResourceWithStreamingResponse:
+ return DownloadsResourceWithStreamingResponse(self._recording.downloads)
+
class AsyncRecordingResourceWithStreamingResponse:
def __init__(self, recording: AsyncRecordingResource) -> None:
@@ -162,3 +190,7 @@ def __init__(self, recording: AsyncRecordingResource) -> None:
self.retrieve = async_to_streamed_response_wrapper(
recording.retrieve,
)
+
+ @cached_property
+ def downloads(self) -> AsyncDownloadsResourceWithStreamingResponse:
+ return AsyncDownloadsResourceWithStreamingResponse(self._recording.downloads)
diff --git a/src/browserbase/resources/sessions/sessions.py b/src/browserbase/resources/sessions/sessions.py
index 8cf81349..4a2210c0 100644
--- a/src/browserbase/resources/sessions/sessions.py
+++ b/src/browserbase/resources/sessions/sessions.py
@@ -43,14 +43,6 @@
DownloadsResourceWithStreamingResponse,
AsyncDownloadsResourceWithStreamingResponse,
)
-from .recording import (
- RecordingResource,
- AsyncRecordingResource,
- RecordingResourceWithRawResponse,
- AsyncRecordingResourceWithRawResponse,
- RecordingResourceWithStreamingResponse,
- AsyncRecordingResourceWithStreamingResponse,
-)
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
to_raw_response_wrapper,
@@ -60,6 +52,14 @@
)
from ..._base_client import make_request_options
from ...types.session import Session
+from .recording.recording import (
+ RecordingResource,
+ AsyncRecordingResource,
+ RecordingResourceWithRawResponse,
+ AsyncRecordingResourceWithRawResponse,
+ RecordingResourceWithStreamingResponse,
+ AsyncRecordingResourceWithStreamingResponse,
+)
from ...types.session_live_urls import SessionLiveURLs
from ...types.session_list_response import SessionListResponse
from ...types.session_create_response import SessionCreateResponse
diff --git a/src/browserbase/types/sessions/recording/__init__.py b/src/browserbase/types/sessions/recording/__init__.py
new file mode 100644
index 00000000..ca016d7f
--- /dev/null
+++ b/src/browserbase/types/sessions/recording/__init__.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .recording_download import RecordingDownload as RecordingDownload
+from .download_list_response import DownloadListResponse as DownloadListResponse
+from .download_create_response import DownloadCreateResponse as DownloadCreateResponse
diff --git a/src/browserbase/types/sessions/recording/download_create_response.py b/src/browserbase/types/sessions/recording/download_create_response.py
new file mode 100644
index 00000000..74815964
--- /dev/null
+++ b/src/browserbase/types/sessions/recording/download_create_response.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ...._models import BaseModel
+from .recording_download import RecordingDownload
+
+__all__ = ["DownloadCreateResponse"]
+
+
+class DownloadCreateResponse(BaseModel):
+ downloads: List[RecordingDownload]
diff --git a/src/browserbase/types/sessions/recording/download_list_response.py b/src/browserbase/types/sessions/recording/download_list_response.py
new file mode 100644
index 00000000..2eb3b4a0
--- /dev/null
+++ b/src/browserbase/types/sessions/recording/download_list_response.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ...._models import BaseModel
+from .recording_download import RecordingDownload
+
+__all__ = ["DownloadListResponse"]
+
+
+class DownloadListResponse(BaseModel):
+ downloads: List[RecordingDownload]
diff --git a/src/browserbase/types/sessions/recording/recording_download.py b/src/browserbase/types/sessions/recording/recording_download.py
new file mode 100644
index 00000000..c6931e44
--- /dev/null
+++ b/src/browserbase/types/sessions/recording/recording_download.py
@@ -0,0 +1,36 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ...._models import BaseModel
+
+__all__ = ["RecordingDownload"]
+
+
+class RecordingDownload(BaseModel):
+ page_id: str = FieldInfo(alias="pageId")
+ """Recorded page (tab) within the session, e.g. "0", "1"."""
+
+ status: Literal["NOT_REQUESTED", "PENDING", "COMPLETED", "FAILED"]
+ """Per-page MP4 assembly state.
+
+ `NOT_REQUESTED`: no download has been requested for the session yet. `PENDING`:
+ assembly is enqueued or in progress. `COMPLETED`: the MP4 is ready. `FAILED`:
+ assembly failed; POST again to retry.
+ """
+
+ completed_at: Optional[datetime] = FieldInfo(alias="completedAt", default=None)
+ """When the MP4 was created.
+
+ Present only when COMPLETED on a standard (non-BYOS) project.
+ """
+
+ download_url: Optional[str] = FieldInfo(alias="downloadUrl", default=None)
+ """Short-lived signed CDN URL, re-minted each GET.
+
+ Present only when COMPLETED on a standard (non-BYOS) project.
+ """
diff --git a/tests/api_resources/sessions/recording/__init__.py b/tests/api_resources/sessions/recording/__init__.py
new file mode 100644
index 00000000..fd8019a9
--- /dev/null
+++ b/tests/api_resources/sessions/recording/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/sessions/recording/test_downloads.py b/tests/api_resources/sessions/recording/test_downloads.py
new file mode 100644
index 00000000..411cc83c
--- /dev/null
+++ b/tests/api_resources/sessions/recording/test_downloads.py
@@ -0,0 +1,176 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from browserbase import Browserbase, AsyncBrowserbase
+from tests.utils import assert_matches_type
+from browserbase.types.sessions.recording import DownloadListResponse, DownloadCreateResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestDownloads:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_create(self, client: Browserbase) -> None:
+ download = client.sessions.recording.downloads.create(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(DownloadCreateResponse, download, path=["response"])
+
+ @parametrize
+ def test_raw_response_create(self, client: Browserbase) -> None:
+ response = client.sessions.recording.downloads.with_raw_response.create(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ download = response.parse()
+ assert_matches_type(DownloadCreateResponse, download, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create(self, client: Browserbase) -> None:
+ with client.sessions.recording.downloads.with_streaming_response.create(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ download = response.parse()
+ assert_matches_type(DownloadCreateResponse, download, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_create(self, client: Browserbase) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.sessions.recording.downloads.with_raw_response.create(
+ "",
+ )
+
+ @parametrize
+ def test_method_list(self, client: Browserbase) -> None:
+ download = client.sessions.recording.downloads.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(DownloadListResponse, download, path=["response"])
+
+ @parametrize
+ def test_raw_response_list(self, client: Browserbase) -> None:
+ response = client.sessions.recording.downloads.with_raw_response.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ download = response.parse()
+ assert_matches_type(DownloadListResponse, download, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list(self, client: Browserbase) -> None:
+ with client.sessions.recording.downloads.with_streaming_response.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ download = response.parse()
+ assert_matches_type(DownloadListResponse, download, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_list(self, client: Browserbase) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.sessions.recording.downloads.with_raw_response.list(
+ "",
+ )
+
+
+class TestAsyncDownloads:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @parametrize
+ async def test_method_create(self, async_client: AsyncBrowserbase) -> None:
+ download = await async_client.sessions.recording.downloads.create(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(DownloadCreateResponse, download, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncBrowserbase) -> None:
+ response = await async_client.sessions.recording.downloads.with_raw_response.create(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ download = await response.parse()
+ assert_matches_type(DownloadCreateResponse, download, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncBrowserbase) -> None:
+ async with async_client.sessions.recording.downloads.with_streaming_response.create(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ download = await response.parse()
+ assert_matches_type(DownloadCreateResponse, download, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_create(self, async_client: AsyncBrowserbase) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.sessions.recording.downloads.with_raw_response.create(
+ "",
+ )
+
+ @parametrize
+ async def test_method_list(self, async_client: AsyncBrowserbase) -> None:
+ download = await async_client.sessions.recording.downloads.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(DownloadListResponse, download, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncBrowserbase) -> None:
+ response = await async_client.sessions.recording.downloads.with_raw_response.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ download = await response.parse()
+ assert_matches_type(DownloadListResponse, download, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncBrowserbase) -> None:
+ async with async_client.sessions.recording.downloads.with_streaming_response.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ download = await response.parse()
+ assert_matches_type(DownloadListResponse, download, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_list(self, async_client: AsyncBrowserbase) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.sessions.recording.downloads.with_raw_response.list(
+ "",
+ )