diff --git a/.stats.yml b/.stats.yml
index c92480be..dd9fa391 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1 +1 @@
-configured_endpoints: 247
+configured_endpoints: 237
diff --git a/api.md b/api.md
index bfeceaed..37b9afc5 100644
--- a/api.md
+++ b/api.md
@@ -431,6 +431,26 @@ Methods:
- client.devices.recordings.trajectory(recording_id, \*, device_id) -> None
- client.devices.recordings.video(recording_id, \*, device_id) -> None
+## TrafficSessions
+
+Types:
+
+```python
+from mobilerun_sdk.types.devices import (
+ TrafficSessionCreateResponse,
+ TrafficSessionRetrieveResponse,
+ TrafficSessionListResponse,
+ TrafficSessionDeleteResponse,
+)
+```
+
+Methods:
+
+- client.devices.traffic_sessions.create(device_id, \*\*params) -> TrafficSessionCreateResponse
+- client.devices.traffic_sessions.retrieve(session_id, \*, device_id) -> TrafficSessionRetrieveResponse
+- client.devices.traffic_sessions.list(device_id, \*\*params) -> TrafficSessionListResponse
+- client.devices.traffic_sessions.delete(session_id, \*, device_id) -> TrafficSessionDeleteResponse
+
# Models
Types:
@@ -688,6 +708,7 @@ from mobilerun_sdk.types.workflows import (
FlowUpdateResponse,
FlowListResponse,
FlowDeleteResponse,
+ FlowCapacityResponse,
FlowCloneResponse,
FlowDryRunResponse,
FlowListRepairsResponse,
@@ -702,6 +723,7 @@ Methods:
- client.workflows.flows.update(flow_id, \*\*params) -> FlowUpdateResponse
- client.workflows.flows.list(\*\*params) -> FlowListResponse
- client.workflows.flows.delete(flow_id) -> FlowDeleteResponse
+- client.workflows.flows.capacity() -> FlowCapacityResponse
- client.workflows.flows.clone(flow_id, \*\*params) -> FlowCloneResponse
- client.workflows.flows.dry_run(flow_id, \*\*params) -> FlowDryRunResponse
- client.workflows.flows.list_repairs(flow_id) -> FlowListRepairsResponse
@@ -867,23 +889,13 @@ Methods:
Types:
```python
-from mobilerun_sdk.types import (
- FileUpdateResponse,
- FileListResponse,
- FileDeleteResponse,
- FileCancelPendingResponse,
- FileConfirmResponse,
- FileUploadURLResponse,
-)
+from mobilerun_sdk.types import FileDeleteResponse, FileCancelPendingResponse, FileUploadURLResponse
```
Methods:
-- client.files.update(file_id, \*\*params) -> FileUpdateResponse
-- client.files.list(\*\*params) -> FileListResponse
- client.files.delete(file_id) -> FileDeleteResponse
- client.files.cancel_pending(file_id) -> FileCancelPendingResponse
-- client.files.confirm(file_id) -> FileConfirmResponse
- client.files.download(file_id) -> None
- client.files.upload_url(\*\*params) -> FileUploadURLResponse
@@ -965,52 +977,6 @@ Methods:
- client.notifications.get_preferences() -> NotificationGetPreferencesResponse
- client.notifications.update_preferences(\*\*params) -> NotificationUpdatePreferencesResponse
-# Esims
-
-Types:
-
-```python
-from mobilerun_sdk.types import (
- EsimCreateResponse,
- EsimRetrieveResponse,
- EsimUpdateResponse,
- EsimListResponse,
- EsimCapacityResponse,
- EsimConfirmPaymentResponse,
- EsimImportResponse,
- EsimInstallResponse,
- EsimInstallStatusResponse,
- EsimSelectorResponse,
-)
-```
-
-Methods:
-
-- client.esims.create(\*\*params) -> EsimCreateResponse
-- client.esims.retrieve(id) -> EsimRetrieveResponse
-- client.esims.update(id, \*\*params) -> EsimUpdateResponse
-- client.esims.list(\*\*params) -> EsimListResponse
-- client.esims.delete(id) -> None
-- client.esims.capacity() -> EsimCapacityResponse
-- client.esims.confirm_payment(id) -> EsimConfirmPaymentResponse
-- client.esims.import\_(\*\*params) -> EsimImportResponse
-- client.esims.install(id, \*\*params) -> EsimInstallResponse
-- client.esims.install_status(id) -> EsimInstallStatusResponse
-- client.esims.selector(\*\*params) -> EsimSelectorResponse
-
-## Messages
-
-Types:
-
-```python
-from mobilerun_sdk.types.esims import MessageListResponse, MessageSendResponse
-```
-
-Methods:
-
-- client.esims.messages.list(id, \*\*params) -> MessageListResponse
-- client.esims.messages.send(id, \*\*params) -> MessageSendResponse
-
# Messages
Types:
@@ -1047,6 +1013,7 @@ from mobilerun_sdk.types import (
NumberUpdateResponse,
NumberListResponse,
NumberDeleteResponse,
+ NumberCapacityResponse,
NumberCountriesResponse,
NumberPurposesResponse,
)
@@ -1059,6 +1026,7 @@ Methods:
- client.numbers.update(id, \*\*params) -> NumberUpdateResponse
- client.numbers.list(\*\*params) -> NumberListResponse
- client.numbers.delete(id) -> NumberDeleteResponse
+- client.numbers.capacity(\*\*params) -> NumberCapacityResponse
- client.numbers.countries() -> NumberCountriesResponse
- client.numbers.purposes() -> NumberPurposesResponse
diff --git a/src/mobilerun_sdk/_client.py b/src/mobilerun_sdk/_client.py
index 4a8abcae..cb8ba65a 100644
--- a/src/mobilerun_sdk/_client.py
+++ b/src/mobilerun_sdk/_client.py
@@ -38,7 +38,6 @@
if TYPE_CHECKING:
from .resources import (
apps,
- esims,
files,
store,
tasks,
@@ -64,7 +63,6 @@
from .resources.proxies import ProxiesResource, AsyncProxiesResource
from .resources.carriers import CarriersResource, AsyncCarriersResource
from .resources.profiles import ProfilesResource, AsyncProfilesResource
- from .resources.esims.esims import EsimsResource, AsyncEsimsResource
from .resources.store.store import StoreResource, AsyncStoreResource
from .resources.tasks.tasks import TasksResource, AsyncTasksResource
from .resources.notifications import NotificationsResource, AsyncNotificationsResource
@@ -249,12 +247,6 @@ def notifications(self) -> NotificationsResource:
return NotificationsResource(self)
- @cached_property
- def esims(self) -> EsimsResource:
- from .resources.esims import EsimsResource
-
- return EsimsResource(self)
-
@cached_property
def messages(self) -> MessagesResource:
from .resources.messages import MessagesResource
@@ -555,12 +547,6 @@ def notifications(self) -> AsyncNotificationsResource:
return AsyncNotificationsResource(self)
- @cached_property
- def esims(self) -> AsyncEsimsResource:
- from .resources.esims import AsyncEsimsResource
-
- return AsyncEsimsResource(self)
-
@cached_property
def messages(self) -> AsyncMessagesResource:
from .resources.messages import AsyncMessagesResource
@@ -807,12 +793,6 @@ def notifications(self) -> notifications.NotificationsResourceWithRawResponse:
return NotificationsResourceWithRawResponse(self._client.notifications)
- @cached_property
- def esims(self) -> esims.EsimsResourceWithRawResponse:
- from .resources.esims import EsimsResourceWithRawResponse
-
- return EsimsResourceWithRawResponse(self._client.esims)
-
@cached_property
def messages(self) -> messages.MessagesResourceWithRawResponse:
from .resources.messages import MessagesResourceWithRawResponse
@@ -936,12 +916,6 @@ def notifications(self) -> notifications.AsyncNotificationsResourceWithRawRespon
return AsyncNotificationsResourceWithRawResponse(self._client.notifications)
- @cached_property
- def esims(self) -> esims.AsyncEsimsResourceWithRawResponse:
- from .resources.esims import AsyncEsimsResourceWithRawResponse
-
- return AsyncEsimsResourceWithRawResponse(self._client.esims)
-
@cached_property
def messages(self) -> messages.AsyncMessagesResourceWithRawResponse:
from .resources.messages import AsyncMessagesResourceWithRawResponse
@@ -1065,12 +1039,6 @@ def notifications(self) -> notifications.NotificationsResourceWithStreamingRespo
return NotificationsResourceWithStreamingResponse(self._client.notifications)
- @cached_property
- def esims(self) -> esims.EsimsResourceWithStreamingResponse:
- from .resources.esims import EsimsResourceWithStreamingResponse
-
- return EsimsResourceWithStreamingResponse(self._client.esims)
-
@cached_property
def messages(self) -> messages.MessagesResourceWithStreamingResponse:
from .resources.messages import MessagesResourceWithStreamingResponse
@@ -1194,12 +1162,6 @@ def notifications(self) -> notifications.AsyncNotificationsResourceWithStreaming
return AsyncNotificationsResourceWithStreamingResponse(self._client.notifications)
- @cached_property
- def esims(self) -> esims.AsyncEsimsResourceWithStreamingResponse:
- from .resources.esims import AsyncEsimsResourceWithStreamingResponse
-
- return AsyncEsimsResourceWithStreamingResponse(self._client.esims)
-
@cached_property
def messages(self) -> messages.AsyncMessagesResourceWithStreamingResponse:
from .resources.messages import AsyncMessagesResourceWithStreamingResponse
diff --git a/src/mobilerun_sdk/resources/__init__.py b/src/mobilerun_sdk/resources/__init__.py
index c86ce259..30c0dbfc 100644
--- a/src/mobilerun_sdk/resources/__init__.py
+++ b/src/mobilerun_sdk/resources/__init__.py
@@ -8,14 +8,6 @@
AppsResourceWithStreamingResponse,
AsyncAppsResourceWithStreamingResponse,
)
-from .esims import (
- EsimsResource,
- AsyncEsimsResource,
- EsimsResourceWithRawResponse,
- AsyncEsimsResourceWithRawResponse,
- EsimsResourceWithStreamingResponse,
- AsyncEsimsResourceWithStreamingResponse,
-)
from .files import (
FilesResource,
AsyncFilesResource,
@@ -258,12 +250,6 @@
"AsyncNotificationsResourceWithRawResponse",
"NotificationsResourceWithStreamingResponse",
"AsyncNotificationsResourceWithStreamingResponse",
- "EsimsResource",
- "AsyncEsimsResource",
- "EsimsResourceWithRawResponse",
- "AsyncEsimsResourceWithRawResponse",
- "EsimsResourceWithStreamingResponse",
- "AsyncEsimsResourceWithStreamingResponse",
"MessagesResource",
"AsyncMessagesResource",
"MessagesResourceWithRawResponse",
diff --git a/src/mobilerun_sdk/resources/apps.py b/src/mobilerun_sdk/resources/apps.py
index e46dbbf0..3f0f323f 100644
--- a/src/mobilerun_sdk/resources/apps.py
+++ b/src/mobilerun_sdk/resources/apps.py
@@ -183,7 +183,9 @@ def confirm_upload(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AppConfirmUploadResponse:
"""
- Verifies the APK file exists in R2 and sets the app status to available.
+ Verifies the uploaded files in R2 and sets the app version status to available.
+ Idempotent: replaying confirmation for an already-available version returns the
+ same successful response without re-verifying the files.
Args:
extra_headers: Send extra headers
@@ -506,7 +508,9 @@ async def confirm_upload(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AppConfirmUploadResponse:
"""
- Verifies the APK file exists in R2 and sets the app status to available.
+ Verifies the uploaded files in R2 and sets the app version status to available.
+ Idempotent: replaying confirmation for an already-available version returns the
+ same successful response without re-verifying the files.
Args:
extra_headers: Send extra headers
diff --git a/src/mobilerun_sdk/resources/assistant/conversations.py b/src/mobilerun_sdk/resources/assistant/conversations.py
index 04b2a56c..a077836d 100644
--- a/src/mobilerun_sdk/resources/assistant/conversations.py
+++ b/src/mobilerun_sdk/resources/assistant/conversations.py
@@ -263,8 +263,14 @@ def answer_permission(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ConversationAnswerPermissionResponse:
- """
- Deliver a HITL approval/rejection for an in-flight turn.
+ """Deliver a HITL approval/rejection for an in-flight turn.
+
+ Interactive HITL
+ clients must start the turn with `Accept: text/event-stream`, wait for a
+ `tool-hitl-approval` event, and send its `permissionId` here at
+ `/assistant/chat/permission`. Do not submit approval as free-form user text or
+ as `confirmed: true`. For `devices.reset`, only `once` and `reject` are allowed;
+ the generic `always` response is rejected with HTTP 400.
Args:
extra_headers: Send extra headers
@@ -428,9 +434,12 @@ def send(
The response format follows the Accept header:
`text/event-stream` for SSE, `application/json` for a buffered assistant reply.
- `sessionId` targets a concrete active chat. The resolved chat session ID is
- returned as `chatSessionId` in the JSON body and as the `X-Chat-Session-Id`
- response header on the SSE response.
+ Interactive HITL requires `Accept: text/event-stream`: the stream can emit a
+ `tool-hitl-approval` event, whose decision must be delivered to
+ `/assistant/chat/permission`. Buffered JSON responses do not provide an
+ interactive HITL continuation contract. `sessionId` targets a concrete active
+ chat. The resolved chat session ID is returned as `chatSessionId` in the JSON
+ body and as the `X-Chat-Session-Id` response header on the SSE response.
Args:
extra_headers: Send extra headers
@@ -721,8 +730,14 @@ async def answer_permission(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ConversationAnswerPermissionResponse:
- """
- Deliver a HITL approval/rejection for an in-flight turn.
+ """Deliver a HITL approval/rejection for an in-flight turn.
+
+ Interactive HITL
+ clients must start the turn with `Accept: text/event-stream`, wait for a
+ `tool-hitl-approval` event, and send its `permissionId` here at
+ `/assistant/chat/permission`. Do not submit approval as free-form user text or
+ as `confirmed: true`. For `devices.reset`, only `once` and `reject` are allowed;
+ the generic `always` response is rejected with HTTP 400.
Args:
extra_headers: Send extra headers
@@ -886,9 +901,12 @@ async def send(
The response format follows the Accept header:
`text/event-stream` for SSE, `application/json` for a buffered assistant reply.
- `sessionId` targets a concrete active chat. The resolved chat session ID is
- returned as `chatSessionId` in the JSON body and as the `X-Chat-Session-Id`
- response header on the SSE response.
+ Interactive HITL requires `Accept: text/event-stream`: the stream can emit a
+ `tool-hitl-approval` event, whose decision must be delivered to
+ `/assistant/chat/permission`. Buffered JSON responses do not provide an
+ interactive HITL continuation contract. `sessionId` targets a concrete active
+ chat. The resolved chat session ID is returned as `chatSessionId` in the JSON
+ body and as the `X-Chat-Session-Id` response header on the SSE response.
Args:
extra_headers: Send extra headers
diff --git a/src/mobilerun_sdk/resources/connect/proxies.py b/src/mobilerun_sdk/resources/connect/proxies.py
index c89fce4c..718dc6d6 100644
--- a/src/mobilerun_sdk/resources/connect/proxies.py
+++ b/src/mobilerun_sdk/resources/connect/proxies.py
@@ -9,7 +9,7 @@
import httpx
from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
-from ..._utils import path_template, maybe_transform, async_maybe_transform
+from ..._utils import path_template, maybe_transform, strip_not_given, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -140,6 +140,7 @@ def buy(
*,
country: str,
type: Literal["dedicated_residential", "residential", "mobile"],
+ idempotency_key: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -161,6 +162,7 @@ def buy(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})}
return self._post(
"/connect/proxies",
body=maybe_transform(
@@ -505,6 +507,7 @@ async def buy(
*,
country: str,
type: Literal["dedicated_residential", "residential", "mobile"],
+ idempotency_key: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -526,6 +529,7 @@ async def buy(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})}
return await self._post(
"/connect/proxies",
body=await async_maybe_transform(
diff --git a/src/mobilerun_sdk/resources/devices/__init__.py b/src/mobilerun_sdk/resources/devices/__init__.py
index 7a429240..17516758 100644
--- a/src/mobilerun_sdk/resources/devices/__init__.py
+++ b/src/mobilerun_sdk/resources/devices/__init__.py
@@ -160,6 +160,14 @@
MediaSessionsResourceWithStreamingResponse,
AsyncMediaSessionsResourceWithStreamingResponse,
)
+from .traffic_sessions import (
+ TrafficSessionsResource,
+ AsyncTrafficSessionsResource,
+ TrafficSessionsResourceWithRawResponse,
+ AsyncTrafficSessionsResourceWithRawResponse,
+ TrafficSessionsResourceWithStreamingResponse,
+ AsyncTrafficSessionsResourceWithStreamingResponse,
+)
__all__ = [
"ActionsResource",
@@ -276,6 +284,12 @@
"AsyncRecordingsResourceWithRawResponse",
"RecordingsResourceWithStreamingResponse",
"AsyncRecordingsResourceWithStreamingResponse",
+ "TrafficSessionsResource",
+ "AsyncTrafficSessionsResource",
+ "TrafficSessionsResourceWithRawResponse",
+ "AsyncTrafficSessionsResourceWithRawResponse",
+ "TrafficSessionsResourceWithStreamingResponse",
+ "AsyncTrafficSessionsResourceWithStreamingResponse",
"DevicesResource",
"AsyncDevicesResource",
"DevicesResourceWithRawResponse",
diff --git a/src/mobilerun_sdk/resources/devices/apps.py b/src/mobilerun_sdk/resources/devices/apps.py
index f89729c8..e672a017 100644
--- a/src/mobilerun_sdk/resources/devices/apps.py
+++ b/src/mobilerun_sdk/resources/devices/apps.py
@@ -207,7 +207,9 @@ def install(
*,
bundle_id: str,
background: bool | Omit = omit,
+ country: str | Omit = omit,
package_name: str | Omit = omit,
+ version_code: int | Omit = omit,
x_device_display_id: 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.
@@ -219,15 +221,16 @@ def install(
"""Requests an app install on the device.
The request body must supply exactly one
- of an Android packageName or an iOS bundleId; protected packages are rejected.
- background (default false) selects the response contract: false installs inline
- and returns the outcome directly (200 on success, an error status on failure);
- true accepts the request and runs the download + install in the background,
- returning 202 immediately — poll list-app-installs for the backend's view of
- that attempt's status. Refuses with 409 once 2 other installs are already
- running on the device, in either mode; a repeat request for an app that already
- has an install running is also refused with 409 rather than superseding it —
- retry once that attempt reaches a terminal state.
+ of an Android packageName or an iOS bundleId; optional country and versionCode
+ select an exact regional uploaded Android version, and protected packages are
+ rejected. background (default false) selects the response contract: false
+ installs inline and returns the outcome directly (200 on success, an error
+ status on failure); true accepts the request and runs the download + install in
+ the background, returning 202 immediately — poll list-app-installs for the
+ backend's view of that attempt's status. Refuses with 409 once 2 other installs
+ are already running on the device, in either mode; a repeat request for an app
+ that already has an install running is also refused with 409 rather than
+ superseding it — retry once that attempt reaches a terminal state.
Args:
bundle_id: iOS bundle identifier (e.g. com.example.app)
@@ -236,8 +239,13 @@ def install(
list-app-installs). false/omitted: install inline and return the outcome
directly (200 on success, an error status on failure).
+ country: Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g. MY or SG).
+
package_name: Android package name (e.g. com.example.app)
+ version_code: Optional exact app-library version code. Use with country when multiple regional
+ versions share an identifier.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -256,6 +264,8 @@ def install(
package_name: str,
background: bool | Omit = omit,
bundle_id: str | Omit = omit,
+ country: str | Omit = omit,
+ version_code: int | Omit = omit,
x_device_display_id: 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.
@@ -267,15 +277,16 @@ def install(
"""Requests an app install on the device.
The request body must supply exactly one
- of an Android packageName or an iOS bundleId; protected packages are rejected.
- background (default false) selects the response contract: false installs inline
- and returns the outcome directly (200 on success, an error status on failure);
- true accepts the request and runs the download + install in the background,
- returning 202 immediately — poll list-app-installs for the backend's view of
- that attempt's status. Refuses with 409 once 2 other installs are already
- running on the device, in either mode; a repeat request for an app that already
- has an install running is also refused with 409 rather than superseding it —
- retry once that attempt reaches a terminal state.
+ of an Android packageName or an iOS bundleId; optional country and versionCode
+ select an exact regional uploaded Android version, and protected packages are
+ rejected. background (default false) selects the response contract: false
+ installs inline and returns the outcome directly (200 on success, an error
+ status on failure); true accepts the request and runs the download + install in
+ the background, returning 202 immediately — poll list-app-installs for the
+ backend's view of that attempt's status. Refuses with 409 once 2 other installs
+ are already running on the device, in either mode; a repeat request for an app
+ that already has an install running is also refused with 409 rather than
+ superseding it — retry once that attempt reaches a terminal state.
Args:
package_name: Android package name (e.g. com.example.app)
@@ -286,6 +297,11 @@ def install(
bundle_id: iOS bundle identifier (e.g. com.example.app)
+ country: Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g. MY or SG).
+
+ version_code: Optional exact app-library version code. Use with country when multiple regional
+ versions share an identifier.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -303,7 +319,9 @@ def install(
*,
bundle_id: str | Omit = omit,
background: bool | Omit = omit,
+ country: str | Omit = omit,
package_name: str | Omit = omit,
+ version_code: int | Omit = omit,
x_device_display_id: 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.
@@ -327,7 +345,9 @@ def install(
{
"bundle_id": bundle_id,
"background": background,
+ "country": country,
"package_name": package_name,
+ "version_code": version_code,
},
app_install_params.AppInstallParams,
),
@@ -350,11 +370,11 @@ def list_installs(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AppListInstallsResponse:
"""
- Reports the backend's view of background app-install attempts on this device —
- status reflects the install ATTEMPT, not device ground truth; list-apps remains
- authoritative for what is actually installed. Records are in-memory and lost on
- service restart; terminal records are kept ~15 minutes. Not gated on device
- readiness, so it also answers while the device is offline or crashed.
+ Reports the backend's durable view of background app-install attempts on this
+ device — status reflects the install ATTEMPT, not device ground truth; list-apps
+ remains authoritative for what is actually installed. Terminal and projected
+ timeout records are kept ~15 minutes. Not gated on device readiness, so it also
+ answers while the device is offline or crashed.
Args:
extra_headers: Send extra headers
@@ -719,7 +739,9 @@ async def install(
*,
bundle_id: str,
background: bool | Omit = omit,
+ country: str | Omit = omit,
package_name: str | Omit = omit,
+ version_code: int | Omit = omit,
x_device_display_id: 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.
@@ -731,15 +753,16 @@ async def install(
"""Requests an app install on the device.
The request body must supply exactly one
- of an Android packageName or an iOS bundleId; protected packages are rejected.
- background (default false) selects the response contract: false installs inline
- and returns the outcome directly (200 on success, an error status on failure);
- true accepts the request and runs the download + install in the background,
- returning 202 immediately — poll list-app-installs for the backend's view of
- that attempt's status. Refuses with 409 once 2 other installs are already
- running on the device, in either mode; a repeat request for an app that already
- has an install running is also refused with 409 rather than superseding it —
- retry once that attempt reaches a terminal state.
+ of an Android packageName or an iOS bundleId; optional country and versionCode
+ select an exact regional uploaded Android version, and protected packages are
+ rejected. background (default false) selects the response contract: false
+ installs inline and returns the outcome directly (200 on success, an error
+ status on failure); true accepts the request and runs the download + install in
+ the background, returning 202 immediately — poll list-app-installs for the
+ backend's view of that attempt's status. Refuses with 409 once 2 other installs
+ are already running on the device, in either mode; a repeat request for an app
+ that already has an install running is also refused with 409 rather than
+ superseding it — retry once that attempt reaches a terminal state.
Args:
bundle_id: iOS bundle identifier (e.g. com.example.app)
@@ -748,8 +771,13 @@ async def install(
list-app-installs). false/omitted: install inline and return the outcome
directly (200 on success, an error status on failure).
+ country: Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g. MY or SG).
+
package_name: Android package name (e.g. com.example.app)
+ version_code: Optional exact app-library version code. Use with country when multiple regional
+ versions share an identifier.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -768,6 +796,8 @@ async def install(
package_name: str,
background: bool | Omit = omit,
bundle_id: str | Omit = omit,
+ country: str | Omit = omit,
+ version_code: int | Omit = omit,
x_device_display_id: 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.
@@ -779,15 +809,16 @@ async def install(
"""Requests an app install on the device.
The request body must supply exactly one
- of an Android packageName or an iOS bundleId; protected packages are rejected.
- background (default false) selects the response contract: false installs inline
- and returns the outcome directly (200 on success, an error status on failure);
- true accepts the request and runs the download + install in the background,
- returning 202 immediately — poll list-app-installs for the backend's view of
- that attempt's status. Refuses with 409 once 2 other installs are already
- running on the device, in either mode; a repeat request for an app that already
- has an install running is also refused with 409 rather than superseding it —
- retry once that attempt reaches a terminal state.
+ of an Android packageName or an iOS bundleId; optional country and versionCode
+ select an exact regional uploaded Android version, and protected packages are
+ rejected. background (default false) selects the response contract: false
+ installs inline and returns the outcome directly (200 on success, an error
+ status on failure); true accepts the request and runs the download + install in
+ the background, returning 202 immediately — poll list-app-installs for the
+ backend's view of that attempt's status. Refuses with 409 once 2 other installs
+ are already running on the device, in either mode; a repeat request for an app
+ that already has an install running is also refused with 409 rather than
+ superseding it — retry once that attempt reaches a terminal state.
Args:
package_name: Android package name (e.g. com.example.app)
@@ -798,6 +829,11 @@ async def install(
bundle_id: iOS bundle identifier (e.g. com.example.app)
+ country: Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g. MY or SG).
+
+ version_code: Optional exact app-library version code. Use with country when multiple regional
+ versions share an identifier.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -815,7 +851,9 @@ async def install(
*,
bundle_id: str | Omit = omit,
background: bool | Omit = omit,
+ country: str | Omit = omit,
package_name: str | Omit = omit,
+ version_code: int | Omit = omit,
x_device_display_id: 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.
@@ -839,7 +877,9 @@ async def install(
{
"bundle_id": bundle_id,
"background": background,
+ "country": country,
"package_name": package_name,
+ "version_code": version_code,
},
app_install_params.AppInstallParams,
),
@@ -862,11 +902,11 @@ async def list_installs(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AppListInstallsResponse:
"""
- Reports the backend's view of background app-install attempts on this device —
- status reflects the install ATTEMPT, not device ground truth; list-apps remains
- authoritative for what is actually installed. Records are in-memory and lost on
- service restart; terminal records are kept ~15 minutes. Not gated on device
- readiness, so it also answers while the device is offline or crashed.
+ Reports the backend's durable view of background app-install attempts on this
+ device — status reflects the install ATTEMPT, not device ground truth; list-apps
+ remains authoritative for what is actually installed. Terminal and projected
+ timeout records are kept ~15 minutes. Not gated on device readiness, so it also
+ answers while the device is offline or crashed.
Args:
extra_headers: Send extra headers
diff --git a/src/mobilerun_sdk/resources/devices/devices.py b/src/mobilerun_sdk/resources/devices/devices.py
index ad34958e..beb5138b 100644
--- a/src/mobilerun_sdk/resources/devices/devices.py
+++ b/src/mobilerun_sdk/resources/devices/devices.py
@@ -172,6 +172,14 @@
MediaSessionsResourceWithStreamingResponse,
AsyncMediaSessionsResourceWithStreamingResponse,
)
+from .traffic_sessions import (
+ TrafficSessionsResource,
+ AsyncTrafficSessionsResource,
+ TrafficSessionsResourceWithRawResponse,
+ AsyncTrafficSessionsResourceWithRawResponse,
+ TrafficSessionsResourceWithStreamingResponse,
+ AsyncTrafficSessionsResourceWithStreamingResponse,
+)
from ...types.device_list_response import DeviceListResponse
from ...types.device_count_response import DeviceCountResponse
from ...types.device_create_response import DeviceCreateResponse
@@ -264,6 +272,10 @@ def media_sessions(self) -> MediaSessionsResource:
def recordings(self) -> RecordingsResource:
return RecordingsResource(self._client)
+ @cached_property
+ def traffic_sessions(self) -> TrafficSessionsResource:
+ return TrafficSessionsResource(self._client)
+
@cached_property
def with_raw_response(self) -> DevicesResourceWithRawResponse:
"""
@@ -657,10 +669,9 @@ def resume(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> None:
"""
- Wakes a parked device: capacity is preflighted (the device's data may be
- replicated to another node if its home is full), the device starts running
- again, and per-minute billing resumes. On a device that is not parked this is a
- no-op ready transition.
+ Wakes a parked device: backend readiness and any required capacity are
+ preflighted, the same device starts running again, and per-minute billing
+ resumes. On a device that is not parked this is a no-op ready transition.
Args:
extra_headers: Send extra headers
@@ -951,6 +962,10 @@ def media_sessions(self) -> AsyncMediaSessionsResource:
def recordings(self) -> AsyncRecordingsResource:
return AsyncRecordingsResource(self._client)
+ @cached_property
+ def traffic_sessions(self) -> AsyncTrafficSessionsResource:
+ return AsyncTrafficSessionsResource(self._client)
+
@cached_property
def with_raw_response(self) -> AsyncDevicesResourceWithRawResponse:
"""
@@ -1344,10 +1359,9 @@ async def resume(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> None:
"""
- Wakes a parked device: capacity is preflighted (the device's data may be
- replicated to another node if its home is full), the device starts running
- again, and per-minute billing resumes. On a device that is not parked this is a
- no-op ready transition.
+ Wakes a parked device: backend readiness and any required capacity are
+ preflighted, the same device starts running again, and per-minute billing
+ resumes. On a device that is not parked this is a no-op ready transition.
Args:
extra_headers: Send extra headers
@@ -1681,6 +1695,10 @@ def media_sessions(self) -> MediaSessionsResourceWithRawResponse:
def recordings(self) -> RecordingsResourceWithRawResponse:
return RecordingsResourceWithRawResponse(self._devices.recordings)
+ @cached_property
+ def traffic_sessions(self) -> TrafficSessionsResourceWithRawResponse:
+ return TrafficSessionsResourceWithRawResponse(self._devices.traffic_sessions)
+
class AsyncDevicesResourceWithRawResponse:
def __init__(self, devices: AsyncDevicesResource) -> None:
@@ -1802,6 +1820,10 @@ def media_sessions(self) -> AsyncMediaSessionsResourceWithRawResponse:
def recordings(self) -> AsyncRecordingsResourceWithRawResponse:
return AsyncRecordingsResourceWithRawResponse(self._devices.recordings)
+ @cached_property
+ def traffic_sessions(self) -> AsyncTrafficSessionsResourceWithRawResponse:
+ return AsyncTrafficSessionsResourceWithRawResponse(self._devices.traffic_sessions)
+
class DevicesResourceWithStreamingResponse:
def __init__(self, devices: DevicesResource) -> None:
@@ -1923,6 +1945,10 @@ def media_sessions(self) -> MediaSessionsResourceWithStreamingResponse:
def recordings(self) -> RecordingsResourceWithStreamingResponse:
return RecordingsResourceWithStreamingResponse(self._devices.recordings)
+ @cached_property
+ def traffic_sessions(self) -> TrafficSessionsResourceWithStreamingResponse:
+ return TrafficSessionsResourceWithStreamingResponse(self._devices.traffic_sessions)
+
class AsyncDevicesResourceWithStreamingResponse:
def __init__(self, devices: AsyncDevicesResource) -> None:
@@ -2043,3 +2069,7 @@ def media_sessions(self) -> AsyncMediaSessionsResourceWithStreamingResponse:
@cached_property
def recordings(self) -> AsyncRecordingsResourceWithStreamingResponse:
return AsyncRecordingsResourceWithStreamingResponse(self._devices.recordings)
+
+ @cached_property
+ def traffic_sessions(self) -> AsyncTrafficSessionsResourceWithStreamingResponse:
+ return AsyncTrafficSessionsResourceWithStreamingResponse(self._devices.traffic_sessions)
diff --git a/src/mobilerun_sdk/resources/devices/keyboard.py b/src/mobilerun_sdk/resources/devices/keyboard.py
index a1bd8bbc..dd5439ce 100644
--- a/src/mobilerun_sdk/resources/devices/keyboard.py
+++ b/src/mobilerun_sdk/resources/devices/keyboard.py
@@ -2,6 +2,8 @@
from __future__ import annotations
+from typing_extensions import Literal
+
import httpx
from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
@@ -130,6 +132,7 @@ def write(
*,
text: str,
clear: bool | Omit = omit,
+ completion_mode: Literal["accepted", "committed"] | Omit = omit,
error_rate: float | Omit = omit,
stealth: bool | Omit = omit,
wpm: int | Omit = omit,
@@ -141,13 +144,17 @@ def write(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> None:
- """Types the given text into the focused input field.
+ """Types text into the focused input field.
- Supports optionally clearing
- the field first and a stealth mode that emulates human typing speed and error
- rate on supported devices.
+ The optional completionMode defaults to
+ accepted for backwards-compatible low latency; committed additionally waits for
+ the complete text or a quiescent UI state.
Args:
+ completion_mode: Completion guarantee. accepted returns after the input provider accepts the
+ operation; committed additionally waits for the focused UI state to contain the
+ complete text or become quiescent.
+
error_rate: Per-character mistake rate for humantouch typing. -1 uses server default.
wpm: Words per minute for stealth typing. 0 uses portal default.
@@ -175,6 +182,7 @@ def write(
{
"text": text,
"clear": clear,
+ "completion_mode": completion_mode,
"error_rate": error_rate,
"stealth": stealth,
"wpm": wpm,
@@ -298,6 +306,7 @@ async def write(
*,
text: str,
clear: bool | Omit = omit,
+ completion_mode: Literal["accepted", "committed"] | Omit = omit,
error_rate: float | Omit = omit,
stealth: bool | Omit = omit,
wpm: int | Omit = omit,
@@ -309,13 +318,17 @@ async def write(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> None:
- """Types the given text into the focused input field.
+ """Types text into the focused input field.
- Supports optionally clearing
- the field first and a stealth mode that emulates human typing speed and error
- rate on supported devices.
+ The optional completionMode defaults to
+ accepted for backwards-compatible low latency; committed additionally waits for
+ the complete text or a quiescent UI state.
Args:
+ completion_mode: Completion guarantee. accepted returns after the input provider accepts the
+ operation; committed additionally waits for the focused UI state to contain the
+ complete text or become quiescent.
+
error_rate: Per-character mistake rate for humantouch typing. -1 uses server default.
wpm: Words per minute for stealth typing. 0 uses portal default.
@@ -343,6 +356,7 @@ async def write(
{
"text": text,
"clear": clear,
+ "completion_mode": completion_mode,
"error_rate": error_rate,
"stealth": stealth,
"wpm": wpm,
diff --git a/src/mobilerun_sdk/resources/devices/recordings.py b/src/mobilerun_sdk/resources/devices/recordings.py
index 11ed0b6a..1591a3b8 100644
--- a/src/mobilerun_sdk/resources/devices/recordings.py
+++ b/src/mobilerun_sdk/resources/devices/recordings.py
@@ -135,6 +135,7 @@ def start(
device_id: str,
*,
name: str | Omit = omit,
+ quality: int | Omit = omit,
retention_days: int | Omit = omit,
types: Optional[SequenceNotStr[str]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -148,6 +149,14 @@ def start(
Start a device recording
Args:
+ quality: Capture quality from 1 (lowest) to 10 (full stream quality). Defaults to the
+ device's full quality. Honored by devices recording through the portal stream
+ bridge.
+
+ types: Artifacts to capture: trajectory (input actions), video, and audio (captured
+ into the video artifact, so it requires video; honored by portal stream-bridge
+ recorders). Defaults to trajectory and video.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -163,6 +172,7 @@ def start(
body=maybe_transform(
{
"name": name,
+ "quality": quality,
"retention_days": retention_days,
"types": types,
},
@@ -440,6 +450,7 @@ async def start(
device_id: str,
*,
name: str | Omit = omit,
+ quality: int | Omit = omit,
retention_days: int | Omit = omit,
types: Optional[SequenceNotStr[str]] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -453,6 +464,14 @@ async def start(
Start a device recording
Args:
+ quality: Capture quality from 1 (lowest) to 10 (full stream quality). Defaults to the
+ device's full quality. Honored by devices recording through the portal stream
+ bridge.
+
+ types: Artifacts to capture: trajectory (input actions), video, and audio (captured
+ into the video artifact, so it requires video; honored by portal stream-bridge
+ recorders). Defaults to trajectory and video.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -468,6 +487,7 @@ async def start(
body=await async_maybe_transform(
{
"name": name,
+ "quality": quality,
"retention_days": retention_days,
"types": types,
},
diff --git a/src/mobilerun_sdk/resources/devices/traffic_sessions.py b/src/mobilerun_sdk/resources/devices/traffic_sessions.py
new file mode 100644
index 00000000..3a23caaf
--- /dev/null
+++ b/src/mobilerun_sdk/resources/devices/traffic_sessions.py
@@ -0,0 +1,470 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ..._utils import path_template, maybe_transform, async_maybe_transform
+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.devices import traffic_session_list_params, traffic_session_create_params
+from ...types.devices.traffic_session_list_response import TrafficSessionListResponse
+from ...types.devices.traffic_session_create_response import TrafficSessionCreateResponse
+from ...types.devices.traffic_session_delete_response import TrafficSessionDeleteResponse
+from ...types.devices.traffic_session_retrieve_response import TrafficSessionRetrieveResponse
+
+__all__ = ["TrafficSessionsResource", "AsyncTrafficSessionsResource"]
+
+
+class TrafficSessionsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> TrafficSessionsResourceWithRawResponse:
+ """
+ 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/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers
+ """
+ return TrafficSessionsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> TrafficSessionsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response
+ """
+ return TrafficSessionsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ device_id: str,
+ *,
+ idempotency_key: str,
+ expires_in_seconds: int | Omit = omit,
+ max_body_bytes: 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,
+ ) -> TrafficSessionCreateResponse:
+ """
+ Starts one live-only decoded HTTP/1.1, HTTP/2, HTTP/3 and WebSocket traffic
+ session.
+
+ 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 device_id:
+ raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}")
+ extra_headers = {"Idempotency-Key": idempotency_key, **(extra_headers or {})}
+ return self._post(
+ path_template("/devices/{device_id}/traffic/sessions", device_id=device_id),
+ body=maybe_transform(
+ {
+ "expires_in_seconds": expires_in_seconds,
+ "max_body_bytes": max_body_bytes,
+ },
+ traffic_session_create_params.TrafficSessionCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TrafficSessionCreateResponse,
+ )
+
+ def retrieve(
+ self,
+ session_id: str,
+ *,
+ device_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,
+ ) -> TrafficSessionRetrieveResponse:
+ """
+ Returns status and the device stream credential for a live session.
+
+ 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 device_id:
+ raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}")
+ if not session_id:
+ raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
+ return self._get(
+ path_template(
+ "/devices/{device_id}/traffic/sessions/{session_id}", device_id=device_id, session_id=session_id
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TrafficSessionRetrieveResponse,
+ )
+
+ def list(
+ self,
+ device_id: str,
+ *,
+ page: int | Omit = omit,
+ page_size: 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,
+ ) -> TrafficSessionListResponse:
+ """
+ List device traffic sessions
+
+ 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 device_id:
+ raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}")
+ return self._get(
+ path_template("/devices/{device_id}/traffic/sessions", device_id=device_id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "page": page,
+ "page_size": page_size,
+ },
+ traffic_session_list_params.TrafficSessionListParams,
+ ),
+ ),
+ cast_to=TrafficSessionListResponse,
+ )
+
+ def delete(
+ self,
+ session_id: str,
+ *,
+ device_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,
+ ) -> TrafficSessionDeleteResponse:
+ """
+ Stop device traffic inspection
+
+ 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 device_id:
+ raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}")
+ if not session_id:
+ raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
+ return self._delete(
+ path_template(
+ "/devices/{device_id}/traffic/sessions/{session_id}", device_id=device_id, session_id=session_id
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TrafficSessionDeleteResponse,
+ )
+
+
+class AsyncTrafficSessionsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncTrafficSessionsResourceWithRawResponse:
+ """
+ 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/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncTrafficSessionsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncTrafficSessionsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response
+ """
+ return AsyncTrafficSessionsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ device_id: str,
+ *,
+ idempotency_key: str,
+ expires_in_seconds: int | Omit = omit,
+ max_body_bytes: 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,
+ ) -> TrafficSessionCreateResponse:
+ """
+ Starts one live-only decoded HTTP/1.1, HTTP/2, HTTP/3 and WebSocket traffic
+ session.
+
+ 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 device_id:
+ raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}")
+ extra_headers = {"Idempotency-Key": idempotency_key, **(extra_headers or {})}
+ return await self._post(
+ path_template("/devices/{device_id}/traffic/sessions", device_id=device_id),
+ body=await async_maybe_transform(
+ {
+ "expires_in_seconds": expires_in_seconds,
+ "max_body_bytes": max_body_bytes,
+ },
+ traffic_session_create_params.TrafficSessionCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TrafficSessionCreateResponse,
+ )
+
+ async def retrieve(
+ self,
+ session_id: str,
+ *,
+ device_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,
+ ) -> TrafficSessionRetrieveResponse:
+ """
+ Returns status and the device stream credential for a live session.
+
+ 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 device_id:
+ raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}")
+ if not session_id:
+ raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
+ return await self._get(
+ path_template(
+ "/devices/{device_id}/traffic/sessions/{session_id}", device_id=device_id, session_id=session_id
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TrafficSessionRetrieveResponse,
+ )
+
+ async def list(
+ self,
+ device_id: str,
+ *,
+ page: int | Omit = omit,
+ page_size: 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,
+ ) -> TrafficSessionListResponse:
+ """
+ List device traffic sessions
+
+ 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 device_id:
+ raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}")
+ return await self._get(
+ path_template("/devices/{device_id}/traffic/sessions", device_id=device_id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "page": page,
+ "page_size": page_size,
+ },
+ traffic_session_list_params.TrafficSessionListParams,
+ ),
+ ),
+ cast_to=TrafficSessionListResponse,
+ )
+
+ async def delete(
+ self,
+ session_id: str,
+ *,
+ device_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,
+ ) -> TrafficSessionDeleteResponse:
+ """
+ Stop device traffic inspection
+
+ 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 device_id:
+ raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}")
+ if not session_id:
+ raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
+ return await self._delete(
+ path_template(
+ "/devices/{device_id}/traffic/sessions/{session_id}", device_id=device_id, session_id=session_id
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TrafficSessionDeleteResponse,
+ )
+
+
+class TrafficSessionsResourceWithRawResponse:
+ def __init__(self, traffic_sessions: TrafficSessionsResource) -> None:
+ self._traffic_sessions = traffic_sessions
+
+ self.create = to_raw_response_wrapper(
+ traffic_sessions.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ traffic_sessions.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ traffic_sessions.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ traffic_sessions.delete,
+ )
+
+
+class AsyncTrafficSessionsResourceWithRawResponse:
+ def __init__(self, traffic_sessions: AsyncTrafficSessionsResource) -> None:
+ self._traffic_sessions = traffic_sessions
+
+ self.create = async_to_raw_response_wrapper(
+ traffic_sessions.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ traffic_sessions.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ traffic_sessions.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ traffic_sessions.delete,
+ )
+
+
+class TrafficSessionsResourceWithStreamingResponse:
+ def __init__(self, traffic_sessions: TrafficSessionsResource) -> None:
+ self._traffic_sessions = traffic_sessions
+
+ self.create = to_streamed_response_wrapper(
+ traffic_sessions.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ traffic_sessions.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ traffic_sessions.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ traffic_sessions.delete,
+ )
+
+
+class AsyncTrafficSessionsResourceWithStreamingResponse:
+ def __init__(self, traffic_sessions: AsyncTrafficSessionsResource) -> None:
+ self._traffic_sessions = traffic_sessions
+
+ self.create = async_to_streamed_response_wrapper(
+ traffic_sessions.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ traffic_sessions.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ traffic_sessions.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ traffic_sessions.delete,
+ )
diff --git a/src/mobilerun_sdk/resources/esims/__init__.py b/src/mobilerun_sdk/resources/esims/__init__.py
deleted file mode 100644
index 394c2d72..00000000
--- a/src/mobilerun_sdk/resources/esims/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .esims import (
- EsimsResource,
- AsyncEsimsResource,
- EsimsResourceWithRawResponse,
- AsyncEsimsResourceWithRawResponse,
- EsimsResourceWithStreamingResponse,
- AsyncEsimsResourceWithStreamingResponse,
-)
-from .messages import (
- MessagesResource,
- AsyncMessagesResource,
- MessagesResourceWithRawResponse,
- AsyncMessagesResourceWithRawResponse,
- MessagesResourceWithStreamingResponse,
- AsyncMessagesResourceWithStreamingResponse,
-)
-
-__all__ = [
- "MessagesResource",
- "AsyncMessagesResource",
- "MessagesResourceWithRawResponse",
- "AsyncMessagesResourceWithRawResponse",
- "MessagesResourceWithStreamingResponse",
- "AsyncMessagesResourceWithStreamingResponse",
- "EsimsResource",
- "AsyncEsimsResource",
- "EsimsResourceWithRawResponse",
- "AsyncEsimsResourceWithRawResponse",
- "EsimsResourceWithStreamingResponse",
- "AsyncEsimsResourceWithStreamingResponse",
-]
diff --git a/src/mobilerun_sdk/resources/esims/esims.py b/src/mobilerun_sdk/resources/esims/esims.py
deleted file mode 100644
index 49347cbe..00000000
--- a/src/mobilerun_sdk/resources/esims/esims.py
+++ /dev/null
@@ -1,1286 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-from typing_extensions import Literal
-
-import httpx
-
-from ...types import (
- esim_list_params,
- esim_create_params,
- esim_import_params,
- esim_update_params,
- esim_install_params,
- esim_selector_params,
-)
-from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
-from ..._utils import path_template, maybe_transform, async_maybe_transform
-from .messages import (
- MessagesResource,
- AsyncMessagesResource,
- MessagesResourceWithRawResponse,
- AsyncMessagesResourceWithRawResponse,
- MessagesResourceWithStreamingResponse,
- AsyncMessagesResourceWithStreamingResponse,
-)
-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.esim_list_response import EsimListResponse
-from ...types.esim_create_response import EsimCreateResponse
-from ...types.esim_import_response import EsimImportResponse
-from ...types.esim_update_response import EsimUpdateResponse
-from ...types.esim_install_response import EsimInstallResponse
-from ...types.esim_capacity_response import EsimCapacityResponse
-from ...types.esim_retrieve_response import EsimRetrieveResponse
-from ...types.esim_selector_response import EsimSelectorResponse
-from ...types.esim_install_status_response import EsimInstallStatusResponse
-from ...types.esim_confirm_payment_response import EsimConfirmPaymentResponse
-
-__all__ = ["EsimsResource", "AsyncEsimsResource"]
-
-
-class EsimsResource(SyncAPIResource):
- @cached_property
- def messages(self) -> MessagesResource:
- return MessagesResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> EsimsResourceWithRawResponse:
- """
- 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/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers
- """
- return EsimsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> EsimsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response
- """
- return EsimsResourceWithStreamingResponse(self)
-
- def create(
- self,
- *,
- idempotency_key: str | Omit = omit,
- name: Optional[str] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> EsimCreateResponse:
- """
- Purchases a physical eSIM from available inventory for the authenticated owner.
- Returns 409 when no stock is available, or 402 with a billing checkout URL when
- billing capacity is exhausted.
-
- Args:
- idempotency_key: Client-supplied key; replaying the same key returns the original purchase
- instead of buying again
-
- name: Optional user-defined display label — NFC-normalized, up to 15 GRAPHEMES. Omit
- or null for no label.
-
- 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._post(
- "/numbers/esims",
- body=maybe_transform(
- {
- "idempotency_key": idempotency_key,
- "name": name,
- },
- esim_create_params.EsimCreateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimCreateResponse,
- )
-
- def retrieve(
- 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,
- ) -> EsimRetrieveResponse:
- """
- Retrieves a single physical eSIM.
-
- 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("/numbers/esims/{id}", id=id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimRetrieveResponse,
- )
-
- def update(
- self,
- id: str,
- *,
- msisdn: Optional[str] | Omit = omit,
- name: Optional[str] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> EsimUpdateResponse:
- """Updates the eSIM's self-reported msisdn and/or display name.
-
- Both fields are
- optional, but the request body itself is required. Omitting a field leaves it
- unchanged; setting it to null or an empty string clears it. `name` is capped at
- 15 characters. Available regardless of the eSIM's current status.
-
- Args:
- msisdn: Self-reported E.164 MSISDN for this eSIM's line. Omit to leave unchanged;
- null/empty clears it. An unverified label — never used for routing.
-
- name: User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code
- units; an emoji/flag may span several). Omit to leave unchanged;
- null/empty/whitespace-only clears it.
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not id:
- raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
- return self._patch(
- path_template("/numbers/esims/{id}", id=id),
- body=maybe_transform(
- {
- "msisdn": msisdn,
- "name": name,
- },
- esim_update_params.EsimUpdateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimUpdateResponse,
- )
-
- def list(
- self,
- *,
- mine: Literal["true", "false"] | Omit = omit,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- status: Literal["all", "in_stock", "owned", "installing", "installed", "install_failed", "retired"]
- | 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,
- ) -> EsimListResponse:
- """
- Lists physical eSIMs owned by the authenticated owner.
-
- Args:
- mine: Only include eSIMs created by the calling actor.
-
- 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(
- "/numbers/esims",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "mine": mine,
- "page": page,
- "page_size": page_size,
- "status": status,
- },
- esim_list_params.EsimListParams,
- ),
- ),
- cast_to=EsimListResponse,
- )
-
- def delete(
- self,
- id: str,
- *,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
- """Removes a physical eSIM.
-
- Idempotent — returns 204 for a fresh removal or a
- replay of an already-removed eSIM. An eSIM currently installed on a device is
- uninstalled first, then removed. An eSIM in an intermediate install state
- returns 409 `operator_resolution_required` and requires manual resolution.
- Returns 404 if the eSIM doesn't exist or isn't owned by the caller.
-
- 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}")
- extra_headers = {"Accept": "*/*", **(extra_headers or {})}
- return self._delete(
- path_template("/numbers/esims/{id}", id=id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
- def capacity(
- self,
- *,
- # 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,
- ) -> EsimCapacityResponse:
- """
- Reports whether a free device is currently available, for pre-checking the
- import flow before upload. This is a hint only, not a reservation —
- `POST /esims/import` re-checks availability at submit time.
- """
- return self._get(
- "/numbers/esims/capacity",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimCapacityResponse,
- )
-
- def confirm_payment(
- 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,
- ) -> EsimConfirmPaymentResponse:
- """
- Checks for proof of payment for this eSIM's current rent and confirms it if
- found. If no proof is available yet, returns 200 with the eSIM unchanged rather
- than an error. Always returns the current eSIM state.
-
- 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("/numbers/esims/{id}/confirm-payment", id=id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimConfirmPaymentResponse,
- )
-
- def import_(
- self,
- *,
- auto_install: bool | Omit = omit,
- carrier_name: str | Omit = omit,
- confirmation_code: str | Omit = omit,
- country_code: str | Omit = omit,
- device_id: str | Omit = omit,
- idempotency_key: str | Omit = omit,
- lpa_code: str | Omit = omit,
- matching_id: str | Omit = omit,
- msisdn: str | Omit = omit,
- name: Optional[str] | Omit = omit,
- notes: str | Omit = omit,
- smdp_address: str | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> EsimImportResponse:
- """
- Registers a bring-your-own (BYO) eSIM activation code as owned inventory.
- Provide either `{ smdpAddress, matchingId?, confirmationCode? }` or
- `{ lpaCode }` — supplying both, or neither, returns 400. An optional `name` sets
- a display label on the created eSIM (up to 15 characters).
-
- Subject to per-owner and daily import limits, and disabled entirely unless BYO
- imports are enabled for this deployment (409 `byo_disabled`). Idempotent via
- `idempotencyKey`: replaying the same key with an identical request returns the
- original response; the same key with a different request returns 409
- `idempotency_conflict`.
-
- When rent-first billing is off (default), the import is free — 201 with the
- eSIM. Setting `autoInstall: true` additionally dispatches an install immediately
- after import (`deviceId` may only be set together with `autoInstall`): this
- returns 202 with `{esim, operationId, statusUrl}` when the install claim
- succeeds (poll `GET /esims/{id}/install-status`), or 201 with the eSIM plus
- `installDispatch: {ok: false, reason}` when the install could not be dispatched
- — the import itself still succeeds either way.
-
- When rent-first billing is on, import additionally requires available device
- capacity (409 `device_pool_empty`) and is subject to a per-owner
- awaiting-payment cap (409 `byo_awaiting_payment_cap`). On success the eSIM is
- created `awaiting_payment` and a checkout is started: 201 with
- `{esim, rentStatus, checkoutUrl}` when the checkout URL is ready immediately, or
- 202 with `checkoutUrl: null` otherwise — poll `GET /esims/{id}` until it's
- populated. Once payment is confirmed, install is triggered automatically.
-
- Args:
- auto_install: Rent OFF only: dispatch install-on-device immediately after a successful import.
- No-op when ESIM_BYO_RENT_ENABLED=true.
-
- device_id: physedge device id to auto-install onto; requires autoInstall:true and rent OFF.
- Omit for a random pool device.
-
- idempotency_key: Client-supplied key; replaying the same key+request returns the original import
- instead of importing again
-
- lpa_code: Full LPA activation code
-
- msisdn: Self-reported E.164 MSISDN for this eSIM's line — an unverified label, never
- used for routing
-
- name: User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code
- units; an emoji/flag may span several). Omit/null/empty/whitespace-only leaves
- it unset.
-
- smdp_address: SM-DP+ activation host — bare hostname ONLY, no port/scheme/path.
-
- 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._post(
- "/numbers/esims/import",
- body=maybe_transform(
- {
- "auto_install": auto_install,
- "carrier_name": carrier_name,
- "confirmation_code": confirmation_code,
- "country_code": country_code,
- "device_id": device_id,
- "idempotency_key": idempotency_key,
- "lpa_code": lpa_code,
- "matching_id": matching_id,
- "msisdn": msisdn,
- "name": name,
- "notes": notes,
- "smdp_address": smdp_address,
- },
- esim_import_params.EsimImportParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimImportResponse,
- )
-
- def install(
- self,
- id: str,
- *,
- device_id: str | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> EsimInstallResponse:
- """Installs the eSIM's activation code onto a device.
-
- `deviceId` is optional — omit
- it to use an available device from the pool. This call is asynchronous: it
- returns 202 with `{esim, operationId, statusUrl}` immediately, and the result is
- available by polling `GET /esims/{id}/install-status`. Retrying with the same
- request is safe if a response is lost.
-
- Returns 409 when the eSIM is not in the `owned` state, or when no device is
- currently available (see `reason`). When rent-first billing is enabled, a BYO
- eSIM whose rent isn't active returns 402 with `{esim, rentStatus, checkoutUrl}`
- instead.
-
- Args:
- device_id: physedge device id to install the eSIM onto; omit for a random pool device
-
- 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("/numbers/esims/{id}/install", id=id),
- body=maybe_transform({"device_id": device_id}, esim_install_params.EsimInstallParams),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimInstallResponse,
- )
-
- def install_status(
- 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,
- ) -> EsimInstallStatusResponse:
- """
- Returns the eSIM's current install status, checking for a terminal outcome if an
- install is still in progress.
-
- 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("/numbers/esims/{id}/install-status", id=id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimInstallStatusResponse,
- )
-
- def selector(
- self,
- *,
- page: int | Omit = omit,
- page_size: 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,
- ) -> EsimSelectorResponse:
- """
- Returns a lightweight list (id, msisdn, carrierName, status, masked iccid) for
- use in a message filter dropdown. Unlike `GET /esims`, this includes all
- statuses, including retired eSIMs.
-
- 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
- """
- return self._get(
- "/numbers/esims/selector",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "page": page,
- "page_size": page_size,
- },
- esim_selector_params.EsimSelectorParams,
- ),
- ),
- cast_to=EsimSelectorResponse,
- )
-
-
-class AsyncEsimsResource(AsyncAPIResource):
- @cached_property
- def messages(self) -> AsyncMessagesResource:
- return AsyncMessagesResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> AsyncEsimsResourceWithRawResponse:
- """
- 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/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers
- """
- return AsyncEsimsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncEsimsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response
- """
- return AsyncEsimsResourceWithStreamingResponse(self)
-
- async def create(
- self,
- *,
- idempotency_key: str | Omit = omit,
- name: Optional[str] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> EsimCreateResponse:
- """
- Purchases a physical eSIM from available inventory for the authenticated owner.
- Returns 409 when no stock is available, or 402 with a billing checkout URL when
- billing capacity is exhausted.
-
- Args:
- idempotency_key: Client-supplied key; replaying the same key returns the original purchase
- instead of buying again
-
- name: Optional user-defined display label — NFC-normalized, up to 15 GRAPHEMES. Omit
- or null for no label.
-
- 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 await self._post(
- "/numbers/esims",
- body=await async_maybe_transform(
- {
- "idempotency_key": idempotency_key,
- "name": name,
- },
- esim_create_params.EsimCreateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimCreateResponse,
- )
-
- async def retrieve(
- 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,
- ) -> EsimRetrieveResponse:
- """
- Retrieves a single physical eSIM.
-
- 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("/numbers/esims/{id}", id=id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimRetrieveResponse,
- )
-
- async def update(
- self,
- id: str,
- *,
- msisdn: Optional[str] | Omit = omit,
- name: Optional[str] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> EsimUpdateResponse:
- """Updates the eSIM's self-reported msisdn and/or display name.
-
- Both fields are
- optional, but the request body itself is required. Omitting a field leaves it
- unchanged; setting it to null or an empty string clears it. `name` is capped at
- 15 characters. Available regardless of the eSIM's current status.
-
- Args:
- msisdn: Self-reported E.164 MSISDN for this eSIM's line. Omit to leave unchanged;
- null/empty clears it. An unverified label — never used for routing.
-
- name: User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code
- units; an emoji/flag may span several). Omit to leave unchanged;
- null/empty/whitespace-only clears it.
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not id:
- raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
- return await self._patch(
- path_template("/numbers/esims/{id}", id=id),
- body=await async_maybe_transform(
- {
- "msisdn": msisdn,
- "name": name,
- },
- esim_update_params.EsimUpdateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimUpdateResponse,
- )
-
- async def list(
- self,
- *,
- mine: Literal["true", "false"] | Omit = omit,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- status: Literal["all", "in_stock", "owned", "installing", "installed", "install_failed", "retired"]
- | 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,
- ) -> EsimListResponse:
- """
- Lists physical eSIMs owned by the authenticated owner.
-
- Args:
- mine: Only include eSIMs created by the calling actor.
-
- 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 await self._get(
- "/numbers/esims",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {
- "mine": mine,
- "page": page,
- "page_size": page_size,
- "status": status,
- },
- esim_list_params.EsimListParams,
- ),
- ),
- cast_to=EsimListResponse,
- )
-
- async def delete(
- self,
- id: str,
- *,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
- """Removes a physical eSIM.
-
- Idempotent — returns 204 for a fresh removal or a
- replay of an already-removed eSIM. An eSIM currently installed on a device is
- uninstalled first, then removed. An eSIM in an intermediate install state
- returns 409 `operator_resolution_required` and requires manual resolution.
- Returns 404 if the eSIM doesn't exist or isn't owned by the caller.
-
- 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}")
- extra_headers = {"Accept": "*/*", **(extra_headers or {})}
- return await self._delete(
- path_template("/numbers/esims/{id}", id=id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
- async def capacity(
- self,
- *,
- # 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,
- ) -> EsimCapacityResponse:
- """
- Reports whether a free device is currently available, for pre-checking the
- import flow before upload. This is a hint only, not a reservation —
- `POST /esims/import` re-checks availability at submit time.
- """
- return await self._get(
- "/numbers/esims/capacity",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimCapacityResponse,
- )
-
- async def confirm_payment(
- 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,
- ) -> EsimConfirmPaymentResponse:
- """
- Checks for proof of payment for this eSIM's current rent and confirms it if
- found. If no proof is available yet, returns 200 with the eSIM unchanged rather
- than an error. Always returns the current eSIM state.
-
- 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("/numbers/esims/{id}/confirm-payment", id=id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimConfirmPaymentResponse,
- )
-
- async def import_(
- self,
- *,
- auto_install: bool | Omit = omit,
- carrier_name: str | Omit = omit,
- confirmation_code: str | Omit = omit,
- country_code: str | Omit = omit,
- device_id: str | Omit = omit,
- idempotency_key: str | Omit = omit,
- lpa_code: str | Omit = omit,
- matching_id: str | Omit = omit,
- msisdn: str | Omit = omit,
- name: Optional[str] | Omit = omit,
- notes: str | Omit = omit,
- smdp_address: str | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> EsimImportResponse:
- """
- Registers a bring-your-own (BYO) eSIM activation code as owned inventory.
- Provide either `{ smdpAddress, matchingId?, confirmationCode? }` or
- `{ lpaCode }` — supplying both, or neither, returns 400. An optional `name` sets
- a display label on the created eSIM (up to 15 characters).
-
- Subject to per-owner and daily import limits, and disabled entirely unless BYO
- imports are enabled for this deployment (409 `byo_disabled`). Idempotent via
- `idempotencyKey`: replaying the same key with an identical request returns the
- original response; the same key with a different request returns 409
- `idempotency_conflict`.
-
- When rent-first billing is off (default), the import is free — 201 with the
- eSIM. Setting `autoInstall: true` additionally dispatches an install immediately
- after import (`deviceId` may only be set together with `autoInstall`): this
- returns 202 with `{esim, operationId, statusUrl}` when the install claim
- succeeds (poll `GET /esims/{id}/install-status`), or 201 with the eSIM plus
- `installDispatch: {ok: false, reason}` when the install could not be dispatched
- — the import itself still succeeds either way.
-
- When rent-first billing is on, import additionally requires available device
- capacity (409 `device_pool_empty`) and is subject to a per-owner
- awaiting-payment cap (409 `byo_awaiting_payment_cap`). On success the eSIM is
- created `awaiting_payment` and a checkout is started: 201 with
- `{esim, rentStatus, checkoutUrl}` when the checkout URL is ready immediately, or
- 202 with `checkoutUrl: null` otherwise — poll `GET /esims/{id}` until it's
- populated. Once payment is confirmed, install is triggered automatically.
-
- Args:
- auto_install: Rent OFF only: dispatch install-on-device immediately after a successful import.
- No-op when ESIM_BYO_RENT_ENABLED=true.
-
- device_id: physedge device id to auto-install onto; requires autoInstall:true and rent OFF.
- Omit for a random pool device.
-
- idempotency_key: Client-supplied key; replaying the same key+request returns the original import
- instead of importing again
-
- lpa_code: Full LPA activation code
-
- msisdn: Self-reported E.164 MSISDN for this eSIM's line — an unverified label, never
- used for routing
-
- name: User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code
- units; an emoji/flag may span several). Omit/null/empty/whitespace-only leaves
- it unset.
-
- smdp_address: SM-DP+ activation host — bare hostname ONLY, no port/scheme/path.
-
- 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 await self._post(
- "/numbers/esims/import",
- body=await async_maybe_transform(
- {
- "auto_install": auto_install,
- "carrier_name": carrier_name,
- "confirmation_code": confirmation_code,
- "country_code": country_code,
- "device_id": device_id,
- "idempotency_key": idempotency_key,
- "lpa_code": lpa_code,
- "matching_id": matching_id,
- "msisdn": msisdn,
- "name": name,
- "notes": notes,
- "smdp_address": smdp_address,
- },
- esim_import_params.EsimImportParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimImportResponse,
- )
-
- async def install(
- self,
- id: str,
- *,
- device_id: str | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> EsimInstallResponse:
- """Installs the eSIM's activation code onto a device.
-
- `deviceId` is optional — omit
- it to use an available device from the pool. This call is asynchronous: it
- returns 202 with `{esim, operationId, statusUrl}` immediately, and the result is
- available by polling `GET /esims/{id}/install-status`. Retrying with the same
- request is safe if a response is lost.
-
- Returns 409 when the eSIM is not in the `owned` state, or when no device is
- currently available (see `reason`). When rent-first billing is enabled, a BYO
- eSIM whose rent isn't active returns 402 with `{esim, rentStatus, checkoutUrl}`
- instead.
-
- Args:
- device_id: physedge device id to install the eSIM onto; omit for a random pool device
-
- 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("/numbers/esims/{id}/install", id=id),
- body=await async_maybe_transform({"device_id": device_id}, esim_install_params.EsimInstallParams),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimInstallResponse,
- )
-
- async def install_status(
- 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,
- ) -> EsimInstallStatusResponse:
- """
- Returns the eSIM's current install status, checking for a terminal outcome if an
- install is still in progress.
-
- 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("/numbers/esims/{id}/install-status", id=id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimInstallStatusResponse,
- )
-
- async def selector(
- self,
- *,
- page: int | Omit = omit,
- page_size: 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,
- ) -> EsimSelectorResponse:
- """
- Returns a lightweight list (id, msisdn, carrierName, status, masked iccid) for
- use in a message filter dropdown. Unlike `GET /esims`, this includes all
- statuses, including retired eSIMs.
-
- 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
- """
- return await self._get(
- "/numbers/esims/selector",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {
- "page": page,
- "page_size": page_size,
- },
- esim_selector_params.EsimSelectorParams,
- ),
- ),
- cast_to=EsimSelectorResponse,
- )
-
-
-class EsimsResourceWithRawResponse:
- def __init__(self, esims: EsimsResource) -> None:
- self._esims = esims
-
- self.create = to_raw_response_wrapper(
- esims.create,
- )
- self.retrieve = to_raw_response_wrapper(
- esims.retrieve,
- )
- self.update = to_raw_response_wrapper(
- esims.update,
- )
- self.list = to_raw_response_wrapper(
- esims.list,
- )
- self.delete = to_raw_response_wrapper(
- esims.delete,
- )
- self.capacity = to_raw_response_wrapper(
- esims.capacity,
- )
- self.confirm_payment = to_raw_response_wrapper(
- esims.confirm_payment,
- )
- self.import_ = to_raw_response_wrapper(
- esims.import_,
- )
- self.install = to_raw_response_wrapper(
- esims.install,
- )
- self.install_status = to_raw_response_wrapper(
- esims.install_status,
- )
- self.selector = to_raw_response_wrapper(
- esims.selector,
- )
-
- @cached_property
- def messages(self) -> MessagesResourceWithRawResponse:
- return MessagesResourceWithRawResponse(self._esims.messages)
-
-
-class AsyncEsimsResourceWithRawResponse:
- def __init__(self, esims: AsyncEsimsResource) -> None:
- self._esims = esims
-
- self.create = async_to_raw_response_wrapper(
- esims.create,
- )
- self.retrieve = async_to_raw_response_wrapper(
- esims.retrieve,
- )
- self.update = async_to_raw_response_wrapper(
- esims.update,
- )
- self.list = async_to_raw_response_wrapper(
- esims.list,
- )
- self.delete = async_to_raw_response_wrapper(
- esims.delete,
- )
- self.capacity = async_to_raw_response_wrapper(
- esims.capacity,
- )
- self.confirm_payment = async_to_raw_response_wrapper(
- esims.confirm_payment,
- )
- self.import_ = async_to_raw_response_wrapper(
- esims.import_,
- )
- self.install = async_to_raw_response_wrapper(
- esims.install,
- )
- self.install_status = async_to_raw_response_wrapper(
- esims.install_status,
- )
- self.selector = async_to_raw_response_wrapper(
- esims.selector,
- )
-
- @cached_property
- def messages(self) -> AsyncMessagesResourceWithRawResponse:
- return AsyncMessagesResourceWithRawResponse(self._esims.messages)
-
-
-class EsimsResourceWithStreamingResponse:
- def __init__(self, esims: EsimsResource) -> None:
- self._esims = esims
-
- self.create = to_streamed_response_wrapper(
- esims.create,
- )
- self.retrieve = to_streamed_response_wrapper(
- esims.retrieve,
- )
- self.update = to_streamed_response_wrapper(
- esims.update,
- )
- self.list = to_streamed_response_wrapper(
- esims.list,
- )
- self.delete = to_streamed_response_wrapper(
- esims.delete,
- )
- self.capacity = to_streamed_response_wrapper(
- esims.capacity,
- )
- self.confirm_payment = to_streamed_response_wrapper(
- esims.confirm_payment,
- )
- self.import_ = to_streamed_response_wrapper(
- esims.import_,
- )
- self.install = to_streamed_response_wrapper(
- esims.install,
- )
- self.install_status = to_streamed_response_wrapper(
- esims.install_status,
- )
- self.selector = to_streamed_response_wrapper(
- esims.selector,
- )
-
- @cached_property
- def messages(self) -> MessagesResourceWithStreamingResponse:
- return MessagesResourceWithStreamingResponse(self._esims.messages)
-
-
-class AsyncEsimsResourceWithStreamingResponse:
- def __init__(self, esims: AsyncEsimsResource) -> None:
- self._esims = esims
-
- self.create = async_to_streamed_response_wrapper(
- esims.create,
- )
- self.retrieve = async_to_streamed_response_wrapper(
- esims.retrieve,
- )
- self.update = async_to_streamed_response_wrapper(
- esims.update,
- )
- self.list = async_to_streamed_response_wrapper(
- esims.list,
- )
- self.delete = async_to_streamed_response_wrapper(
- esims.delete,
- )
- self.capacity = async_to_streamed_response_wrapper(
- esims.capacity,
- )
- self.confirm_payment = async_to_streamed_response_wrapper(
- esims.confirm_payment,
- )
- self.import_ = async_to_streamed_response_wrapper(
- esims.import_,
- )
- self.install = async_to_streamed_response_wrapper(
- esims.install,
- )
- self.install_status = async_to_streamed_response_wrapper(
- esims.install_status,
- )
- self.selector = async_to_streamed_response_wrapper(
- esims.selector,
- )
-
- @cached_property
- def messages(self) -> AsyncMessagesResourceWithStreamingResponse:
- return AsyncMessagesResourceWithStreamingResponse(self._esims.messages)
diff --git a/src/mobilerun_sdk/resources/esims/messages.py b/src/mobilerun_sdk/resources/esims/messages.py
deleted file mode 100644
index f6d7efad..00000000
--- a/src/mobilerun_sdk/resources/esims/messages.py
+++ /dev/null
@@ -1,352 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal
-
-import httpx
-
-from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import path_template, maybe_transform, async_maybe_transform
-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 ...types.esims import message_list_params, message_send_params
-from ..._base_client import make_request_options
-from ...types.esims.message_list_response import MessageListResponse
-from ...types.esims.message_send_response import MessageSendResponse
-
-__all__ = ["MessagesResource", "AsyncMessagesResource"]
-
-
-class MessagesResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> MessagesResourceWithRawResponse:
- """
- 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/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers
- """
- return MessagesResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> MessagesResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response
- """
- return MessagesResourceWithStreamingResponse(self)
-
- def list(
- self,
- id: str,
- *,
- direction: Literal["all", "inbound", "outbound"] | Omit = omit,
- number_id: str | Omit = omit,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- peer_key: str | Omit = omit,
- peer_number: str | Omit = omit,
- status: Literal[
- "all", "received", "queued", "claimed", "sending", "sent", "sent_unconfirmed", "delivered", "failed"
- ]
- | 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,
- ) -> MessageListResponse:
- """
- List messages for one eSIM
-
- 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("/numbers/esims/{id}/messages", id=id),
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "direction": direction,
- "number_id": number_id,
- "page": page,
- "page_size": page_size,
- "peer_key": peer_key,
- "peer_number": peer_number,
- "status": status,
- },
- message_list_params.MessageListParams,
- ),
- ),
- cast_to=MessageListResponse,
- )
-
- def send(
- self,
- id: str,
- *,
- body: str,
- to: str,
- client_request_id: str | Omit = omit,
- delivery_report: 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,
- ) -> MessageSendResponse:
- """
- Send an SMS through one eSIM
-
- Args:
- body: SMS body text (max 320 chars — smaller than the admin tier's cap; see the
- schema's own doc comment for why)
-
- to: Recipient phone number — normalized to E.164 (spaces/dashes/dots stripped);
- rejected with 400 if it doesn't validate as E.164 afterward.
-
- client_request_id: Client-supplied idempotency key, scoped to (owner, esimId, key). Replaying the
- same key + identical payload returns the original send; the same key with a
- DIFFERENT payload is a 409 conflict.
-
- delivery_report: Wait for physedge to confirm carrier delivery before completing the send (adds
- executor-side latency, never on this request — sends are always async/202).
- Defaults to false for the public tier (opt-in, unlike the admin tier's
- default-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
- """
- if not id:
- raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
- return self._post(
- path_template("/numbers/esims/{id}/messages", id=id),
- body=maybe_transform(
- {
- "body": body,
- "to": to,
- "client_request_id": client_request_id,
- "delivery_report": delivery_report,
- },
- message_send_params.MessageSendParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=MessageSendResponse,
- )
-
-
-class AsyncMessagesResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncMessagesResourceWithRawResponse:
- """
- 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/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers
- """
- return AsyncMessagesResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncMessagesResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response
- """
- return AsyncMessagesResourceWithStreamingResponse(self)
-
- async def list(
- self,
- id: str,
- *,
- direction: Literal["all", "inbound", "outbound"] | Omit = omit,
- number_id: str | Omit = omit,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- peer_key: str | Omit = omit,
- peer_number: str | Omit = omit,
- status: Literal[
- "all", "received", "queued", "claimed", "sending", "sent", "sent_unconfirmed", "delivered", "failed"
- ]
- | 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,
- ) -> MessageListResponse:
- """
- List messages for one eSIM
-
- 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("/numbers/esims/{id}/messages", id=id),
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {
- "direction": direction,
- "number_id": number_id,
- "page": page,
- "page_size": page_size,
- "peer_key": peer_key,
- "peer_number": peer_number,
- "status": status,
- },
- message_list_params.MessageListParams,
- ),
- ),
- cast_to=MessageListResponse,
- )
-
- async def send(
- self,
- id: str,
- *,
- body: str,
- to: str,
- client_request_id: str | Omit = omit,
- delivery_report: 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,
- ) -> MessageSendResponse:
- """
- Send an SMS through one eSIM
-
- Args:
- body: SMS body text (max 320 chars — smaller than the admin tier's cap; see the
- schema's own doc comment for why)
-
- to: Recipient phone number — normalized to E.164 (spaces/dashes/dots stripped);
- rejected with 400 if it doesn't validate as E.164 afterward.
-
- client_request_id: Client-supplied idempotency key, scoped to (owner, esimId, key). Replaying the
- same key + identical payload returns the original send; the same key with a
- DIFFERENT payload is a 409 conflict.
-
- delivery_report: Wait for physedge to confirm carrier delivery before completing the send (adds
- executor-side latency, never on this request — sends are always async/202).
- Defaults to false for the public tier (opt-in, unlike the admin tier's
- default-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
- """
- if not id:
- raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
- return await self._post(
- path_template("/numbers/esims/{id}/messages", id=id),
- body=await async_maybe_transform(
- {
- "body": body,
- "to": to,
- "client_request_id": client_request_id,
- "delivery_report": delivery_report,
- },
- message_send_params.MessageSendParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=MessageSendResponse,
- )
-
-
-class MessagesResourceWithRawResponse:
- def __init__(self, messages: MessagesResource) -> None:
- self._messages = messages
-
- self.list = to_raw_response_wrapper(
- messages.list,
- )
- self.send = to_raw_response_wrapper(
- messages.send,
- )
-
-
-class AsyncMessagesResourceWithRawResponse:
- def __init__(self, messages: AsyncMessagesResource) -> None:
- self._messages = messages
-
- self.list = async_to_raw_response_wrapper(
- messages.list,
- )
- self.send = async_to_raw_response_wrapper(
- messages.send,
- )
-
-
-class MessagesResourceWithStreamingResponse:
- def __init__(self, messages: MessagesResource) -> None:
- self._messages = messages
-
- self.list = to_streamed_response_wrapper(
- messages.list,
- )
- self.send = to_streamed_response_wrapper(
- messages.send,
- )
-
-
-class AsyncMessagesResourceWithStreamingResponse:
- def __init__(self, messages: AsyncMessagesResource) -> None:
- self._messages = messages
-
- self.list = async_to_streamed_response_wrapper(
- messages.list,
- )
- self.send = async_to_streamed_response_wrapper(
- messages.send,
- )
diff --git a/src/mobilerun_sdk/resources/files.py b/src/mobilerun_sdk/resources/files.py
index 739ba6f8..ee56372d 100644
--- a/src/mobilerun_sdk/resources/files.py
+++ b/src/mobilerun_sdk/resources/files.py
@@ -2,12 +2,11 @@
from __future__ import annotations
-from typing import Optional
from typing_extensions import Literal
import httpx
-from ..types import file_list_params, file_update_params, file_upload_url_params
+from ..types import file_upload_url_params
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
from .._utils import path_template, maybe_transform, strip_not_given, async_maybe_transform
from .._compat import cached_property
@@ -19,10 +18,7 @@
async_to_streamed_response_wrapper,
)
from .._base_client import make_request_options
-from ..types.file_list_response import FileListResponse
from ..types.file_delete_response import FileDeleteResponse
-from ..types.file_update_response import FileUpdateResponse
-from ..types.file_confirm_response import FileConfirmResponse
from ..types.file_upload_url_response import FileUploadURLResponse
from ..types.file_cancel_pending_response import FileCancelPendingResponse
@@ -49,85 +45,6 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse:
"""
return FilesResourceWithStreamingResponse(self)
- def update(
- self,
- file_id: str,
- *,
- display_name: Optional[str] | Omit = omit,
- enabled: 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,
- ) -> FileUpdateResponse:
- """Partial update of `displayName` and/or `enabled`.
-
- Only files with `zone=skills`
- are mutable; other zones return 422 `unsupported_zone`.
-
- 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 file_id:
- raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
- return self._patch(
- path_template("/agents/files/{file_id}", file_id=file_id),
- body=maybe_transform(
- {
- "display_name": display_name,
- "enabled": enabled,
- },
- file_update_params.FileUpdateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=FileUpdateResponse,
- )
-
- def list(
- self,
- *,
- zone: Literal["user", "agent", "workflow", "skills"] | 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,
- ) -> FileListResponse:
- """
- List the user's ready files, optionally filtered by zone
-
- 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
- """
- return self._get(
- "/agents/files",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform({"zone": zone}, file_list_params.FileListParams),
- ),
- cast_to=FileListResponse,
- )
-
def delete(
self,
file_id: str,
@@ -197,39 +114,6 @@ def cancel_pending(
cast_to=FileCancelPendingResponse,
)
- def confirm(
- self,
- file_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,
- ) -> FileConfirmResponse:
- """
- Confirm a file upload by server-side HEAD validation
-
- 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 file_id:
- raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
- return self._post(
- path_template("/agents/files/{file_id}/confirm", file_id=file_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=FileConfirmResponse,
- )
-
def download(
self,
file_id: str,
@@ -332,85 +216,6 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse:
"""
return AsyncFilesResourceWithStreamingResponse(self)
- async def update(
- self,
- file_id: str,
- *,
- display_name: Optional[str] | Omit = omit,
- enabled: 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,
- ) -> FileUpdateResponse:
- """Partial update of `displayName` and/or `enabled`.
-
- Only files with `zone=skills`
- are mutable; other zones return 422 `unsupported_zone`.
-
- 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 file_id:
- raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
- return await self._patch(
- path_template("/agents/files/{file_id}", file_id=file_id),
- body=await async_maybe_transform(
- {
- "display_name": display_name,
- "enabled": enabled,
- },
- file_update_params.FileUpdateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=FileUpdateResponse,
- )
-
- async def list(
- self,
- *,
- zone: Literal["user", "agent", "workflow", "skills"] | 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,
- ) -> FileListResponse:
- """
- List the user's ready files, optionally filtered by zone
-
- 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
- """
- return await self._get(
- "/agents/files",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform({"zone": zone}, file_list_params.FileListParams),
- ),
- cast_to=FileListResponse,
- )
-
async def delete(
self,
file_id: str,
@@ -480,39 +285,6 @@ async def cancel_pending(
cast_to=FileCancelPendingResponse,
)
- async def confirm(
- self,
- file_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,
- ) -> FileConfirmResponse:
- """
- Confirm a file upload by server-side HEAD validation
-
- 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 file_id:
- raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
- return await self._post(
- path_template("/agents/files/{file_id}/confirm", file_id=file_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=FileConfirmResponse,
- )
-
async def download(
self,
file_id: str,
@@ -599,21 +371,12 @@ class FilesResourceWithRawResponse:
def __init__(self, files: FilesResource) -> None:
self._files = files
- self.update = to_raw_response_wrapper(
- files.update,
- )
- self.list = to_raw_response_wrapper(
- files.list,
- )
self.delete = to_raw_response_wrapper(
files.delete,
)
self.cancel_pending = to_raw_response_wrapper(
files.cancel_pending,
)
- self.confirm = to_raw_response_wrapper(
- files.confirm,
- )
self.download = to_raw_response_wrapper(
files.download,
)
@@ -626,21 +389,12 @@ class AsyncFilesResourceWithRawResponse:
def __init__(self, files: AsyncFilesResource) -> None:
self._files = files
- self.update = async_to_raw_response_wrapper(
- files.update,
- )
- self.list = async_to_raw_response_wrapper(
- files.list,
- )
self.delete = async_to_raw_response_wrapper(
files.delete,
)
self.cancel_pending = async_to_raw_response_wrapper(
files.cancel_pending,
)
- self.confirm = async_to_raw_response_wrapper(
- files.confirm,
- )
self.download = async_to_raw_response_wrapper(
files.download,
)
@@ -653,21 +407,12 @@ class FilesResourceWithStreamingResponse:
def __init__(self, files: FilesResource) -> None:
self._files = files
- self.update = to_streamed_response_wrapper(
- files.update,
- )
- self.list = to_streamed_response_wrapper(
- files.list,
- )
self.delete = to_streamed_response_wrapper(
files.delete,
)
self.cancel_pending = to_streamed_response_wrapper(
files.cancel_pending,
)
- self.confirm = to_streamed_response_wrapper(
- files.confirm,
- )
self.download = to_streamed_response_wrapper(
files.download,
)
@@ -680,21 +425,12 @@ class AsyncFilesResourceWithStreamingResponse:
def __init__(self, files: AsyncFilesResource) -> None:
self._files = files
- self.update = async_to_streamed_response_wrapper(
- files.update,
- )
- self.list = async_to_streamed_response_wrapper(
- files.list,
- )
self.delete = async_to_streamed_response_wrapper(
files.delete,
)
self.cancel_pending = async_to_streamed_response_wrapper(
files.cancel_pending,
)
- self.confirm = async_to_streamed_response_wrapper(
- files.confirm,
- )
self.download = async_to_streamed_response_wrapper(
files.download,
)
diff --git a/src/mobilerun_sdk/resources/mailboxes/mailboxes.py b/src/mobilerun_sdk/resources/mailboxes/mailboxes.py
index 0a62f3c9..50e03570 100644
--- a/src/mobilerun_sdk/resources/mailboxes/mailboxes.py
+++ b/src/mobilerun_sdk/resources/mailboxes/mailboxes.py
@@ -75,7 +75,8 @@ def create(
self,
*,
client_request_id: str,
- billing_preference: Literal["included", "rent"] | Omit = omit,
+ billing_preference: Literal["included", "included_only", "rent"] | Omit = omit,
+ domain_id: str | Omit = omit,
label: str | Omit = omit,
local_part: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -85,22 +86,22 @@ def create(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxCreateResponse:
- """
- Reserves a permanently-allocated, individually-rented mailbox and starts an
- Autumn rental checkout. An optional localPart selects the full address local
- part; omitting it keeps the default random, non-guessable mx\\__-prefixed address.
- The address is withheld until the first payment is confirmed. Idempotent on
- (owner, clientRequestId): same key + payload replays (200); a conflicting or
- already-held local part returns 409. 201 when the checkout URL is already
- persisted, otherwise 202 (poll GET for the URL).
+ """Creates a mailbox on the default domain or a connected custom domain.
+
+ An
+ optional `localPart` selects the address. Replaying the same `clientRequestId`
+ and payload returns the original mailbox. Poll the mailbox when a 202 response
+ does not yet include a checkout URL.
Args:
- billing_preference: Funding preference. Omit or use included for included-first activation; rent
- always preserves package capacity and starts paid checkout.
+ billing_preference: included uses package capacity when available and otherwise starts paid
+ checkout; included_only fails without creating a paid reservation when no
+ included slot remains; rent always starts paid checkout.
+
+ domain_id: Optional active custom mailbox domain owned by the caller. Omit to use the
+ system domain.
- local_part: Optional full mailbox local part (the address before "@"). Trimmed and
- lowercased before validation. Omit for a random, non-guessable mx\\__-prefixed
- address.
+ local_part: Optional mailbox name before the "@". Omit to generate a random address.
extra_headers: Send extra headers
@@ -116,6 +117,7 @@ def create(
{
"client_request_id": client_request_id,
"billing_preference": billing_preference,
+ "domain_id": domain_id,
"label": label,
"local_part": local_part,
},
@@ -248,12 +250,9 @@ def delete(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxDeleteResponse:
- """For paid rent, schedules end-of-cycle cancellation.
-
- For an included generation,
- archives immediately and releases its package seat. This never deletes the
- mailbox, its address, or its messages — the address is permanently reserved.
- Idempotent.
+ """
+ Cancels a pending mailbox or schedules an active paid mailbox for cancellation.
+ Existing addresses and messages are retained. Repeating the request is safe.
Args:
extra_headers: Send extra headers
@@ -284,10 +283,7 @@ def capacity(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxCapacityResponse:
- """
- Returns the authoritative number of package-funded mailbox claims currently
- available after local reservations.
- """
+ """Returns the number of mailboxes currently available through included capacity."""
return self._get(
"/mailboxes/capacity",
options=make_request_options(
@@ -311,10 +307,10 @@ def otp(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxOtpResponse:
- """
- Returns the highest-confidence, most recent OTP for the mailbox, restricted to
- messages of completed/active paid intervals. Does not wait server-side (SDKs
- poll). 200 with the best code, 204 when none matches.
+ """Returns the most likely recent OTP for the mailbox.
+
+ Returns 204 when no matching
+ code is available.
Args:
extra_headers: Send extra headers
@@ -351,7 +347,7 @@ def restart(
self,
mailbox_id: str,
*,
- billing_preference: Literal["included", "rent"] | Omit = omit,
+ billing_preference: Literal["included", "included_only", "rent"] | 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,
@@ -359,13 +355,15 @@ def restart(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxRestartResponse:
- """
- Starts a new generation on an archived mailbox, reusing the same permanent
- address. Uses included capacity first unless paid rent is requested.
+ """Restarts an archived mailbox with the same address.
+
+ Uses included capacity when
+ available unless paid service is requested.
Args:
- billing_preference: Funding preference. Omit or use included for included-first activation; rent
- always preserves package capacity and starts paid checkout.
+ billing_preference: included uses package capacity when available and otherwise starts paid
+ checkout; included_only fails without creating a paid reservation when no
+ included slot remains; rent always starts paid checkout.
extra_headers: Send extra headers
@@ -399,10 +397,10 @@ def uncancel(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxUncancelResponse:
- """Retracts a scheduled end-of-cycle cancellation for the current generation.
+ """Withdraws a scheduled cancellation.
- Only
- valid while cancellation is pending.
+ Only available while cancellation is
+ pending.
Args:
extra_headers: Send extra headers
@@ -452,7 +450,8 @@ async def create(
self,
*,
client_request_id: str,
- billing_preference: Literal["included", "rent"] | Omit = omit,
+ billing_preference: Literal["included", "included_only", "rent"] | Omit = omit,
+ domain_id: str | Omit = omit,
label: str | Omit = omit,
local_part: str | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -462,22 +461,22 @@ async def create(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxCreateResponse:
- """
- Reserves a permanently-allocated, individually-rented mailbox and starts an
- Autumn rental checkout. An optional localPart selects the full address local
- part; omitting it keeps the default random, non-guessable mx\\__-prefixed address.
- The address is withheld until the first payment is confirmed. Idempotent on
- (owner, clientRequestId): same key + payload replays (200); a conflicting or
- already-held local part returns 409. 201 when the checkout URL is already
- persisted, otherwise 202 (poll GET for the URL).
+ """Creates a mailbox on the default domain or a connected custom domain.
+
+ An
+ optional `localPart` selects the address. Replaying the same `clientRequestId`
+ and payload returns the original mailbox. Poll the mailbox when a 202 response
+ does not yet include a checkout URL.
Args:
- billing_preference: Funding preference. Omit or use included for included-first activation; rent
- always preserves package capacity and starts paid checkout.
+ billing_preference: included uses package capacity when available and otherwise starts paid
+ checkout; included_only fails without creating a paid reservation when no
+ included slot remains; rent always starts paid checkout.
+
+ domain_id: Optional active custom mailbox domain owned by the caller. Omit to use the
+ system domain.
- local_part: Optional full mailbox local part (the address before "@"). Trimmed and
- lowercased before validation. Omit for a random, non-guessable mx\\__-prefixed
- address.
+ local_part: Optional mailbox name before the "@". Omit to generate a random address.
extra_headers: Send extra headers
@@ -493,6 +492,7 @@ async def create(
{
"client_request_id": client_request_id,
"billing_preference": billing_preference,
+ "domain_id": domain_id,
"label": label,
"local_part": local_part,
},
@@ -625,12 +625,9 @@ async def delete(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxDeleteResponse:
- """For paid rent, schedules end-of-cycle cancellation.
-
- For an included generation,
- archives immediately and releases its package seat. This never deletes the
- mailbox, its address, or its messages — the address is permanently reserved.
- Idempotent.
+ """
+ Cancels a pending mailbox or schedules an active paid mailbox for cancellation.
+ Existing addresses and messages are retained. Repeating the request is safe.
Args:
extra_headers: Send extra headers
@@ -661,10 +658,7 @@ async def capacity(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxCapacityResponse:
- """
- Returns the authoritative number of package-funded mailbox claims currently
- available after local reservations.
- """
+ """Returns the number of mailboxes currently available through included capacity."""
return await self._get(
"/mailboxes/capacity",
options=make_request_options(
@@ -688,10 +682,10 @@ async def otp(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxOtpResponse:
- """
- Returns the highest-confidence, most recent OTP for the mailbox, restricted to
- messages of completed/active paid intervals. Does not wait server-side (SDKs
- poll). 200 with the best code, 204 when none matches.
+ """Returns the most likely recent OTP for the mailbox.
+
+ Returns 204 when no matching
+ code is available.
Args:
extra_headers: Send extra headers
@@ -728,7 +722,7 @@ async def restart(
self,
mailbox_id: str,
*,
- billing_preference: Literal["included", "rent"] | Omit = omit,
+ billing_preference: Literal["included", "included_only", "rent"] | 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,
@@ -736,13 +730,15 @@ async def restart(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxRestartResponse:
- """
- Starts a new generation on an archived mailbox, reusing the same permanent
- address. Uses included capacity first unless paid rent is requested.
+ """Restarts an archived mailbox with the same address.
+
+ Uses included capacity when
+ available unless paid service is requested.
Args:
- billing_preference: Funding preference. Omit or use included for included-first activation; rent
- always preserves package capacity and starts paid checkout.
+ billing_preference: included uses package capacity when available and otherwise starts paid
+ checkout; included_only fails without creating a paid reservation when no
+ included slot remains; rent always starts paid checkout.
extra_headers: Send extra headers
@@ -776,10 +772,10 @@ async def uncancel(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MailboxUncancelResponse:
- """Retracts a scheduled end-of-cycle cancellation for the current generation.
+ """Withdraws a scheduled cancellation.
- Only
- valid while cancellation is pending.
+ Only available while cancellation is
+ pending.
Args:
extra_headers: Send extra headers
diff --git a/src/mobilerun_sdk/resources/mailboxes/messages.py b/src/mobilerun_sdk/resources/mailboxes/messages.py
index d1baa1f8..2e7c54cd 100644
--- a/src/mobilerun_sdk/resources/mailboxes/messages.py
+++ b/src/mobilerun_sdk/resources/mailboxes/messages.py
@@ -101,8 +101,8 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MessageListResponse:
"""
- Lists messages for a mailbox with keyset pagination and time/sender/hasOtp
- filters for polling.
+ Lists mailbox messages with cursor pagination and optional time, sender, and OTP
+ filters.
Args:
extra_headers: Send extra headers
@@ -212,8 +212,8 @@ async def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MessageListResponse:
"""
- Lists messages for a mailbox with keyset pagination and time/sender/hasOtp
- filters for polling.
+ Lists mailbox messages with cursor pagination and optional time, sender, and OTP
+ filters.
Args:
extra_headers: Send extra headers
diff --git a/src/mobilerun_sdk/resources/messages/conversations.py b/src/mobilerun_sdk/resources/messages/conversations.py
index 9ef14bfa..397a5a3e 100644
--- a/src/mobilerun_sdk/resources/messages/conversations.py
+++ b/src/mobilerun_sdk/resources/messages/conversations.py
@@ -60,19 +60,10 @@ def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ConversationListResponse:
- """Lists the caller's own SMS conversations, one row per thread.
+ """Lists SMS conversations by recent activity.
- Each row includes
- the most recent message in the thread, its unread inbound count, and the eSIMs
- it was seen through. Optional `esimId` or `numberId` narrows to threads on one
- eSIM or number.
-
- Cursor-paginated via `limit` (default 20, max 100) and
- `cursorLastOccurredAt`/`cursorLastMessageId` (both required together, taken from
- a previous page's `nextCursor`). Pagination follows each thread's most recent
- activity rather than a fixed snapshot, so a thread with new activity can move
- ahead of an in-progress page fetch. Clients that need a stable ordering should
- snapshot their own view.
+ Use both cursor fields from
+ `nextCursor` to fetch the next page.
Args:
extra_headers: Send extra headers
@@ -118,10 +109,8 @@ def mark_read(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ConversationMarkReadResponse:
"""
- Marks the caller's own inbound messages in a conversation thread as read, up to
- and including the given `(upToOccurredAt, upToMessageId)` cursor — typically a
- conversation row's `lastMessage`. Idempotent: repeating the call with the same
- cursor updates 0 rows. Returns the number of rows updated.
+ Marks inbound messages in a conversation as read through the supplied cursor.
+ Repeating the request is safe.
Args:
peer_key: The thread's canonical peer key (see GET .../conversations)
@@ -189,19 +178,10 @@ async def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ConversationListResponse:
- """Lists the caller's own SMS conversations, one row per thread.
-
- Each row includes
- the most recent message in the thread, its unread inbound count, and the eSIMs
- it was seen through. Optional `esimId` or `numberId` narrows to threads on one
- eSIM or number.
+ """Lists SMS conversations by recent activity.
- Cursor-paginated via `limit` (default 20, max 100) and
- `cursorLastOccurredAt`/`cursorLastMessageId` (both required together, taken from
- a previous page's `nextCursor`). Pagination follows each thread's most recent
- activity rather than a fixed snapshot, so a thread with new activity can move
- ahead of an in-progress page fetch. Clients that need a stable ordering should
- snapshot their own view.
+ Use both cursor fields from
+ `nextCursor` to fetch the next page.
Args:
extra_headers: Send extra headers
@@ -247,10 +227,8 @@ async def mark_read(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ConversationMarkReadResponse:
"""
- Marks the caller's own inbound messages in a conversation thread as read, up to
- and including the given `(upToOccurredAt, upToMessageId)` cursor — typically a
- conversation row's `lastMessage`. Idempotent: repeating the call with the same
- cursor updates 0 rows. Returns the number of rows updated.
+ Marks inbound messages in a conversation as read through the supplied cursor.
+ Repeating the request is safe.
Args:
peer_key: The thread's canonical peer key (see GET .../conversations)
diff --git a/src/mobilerun_sdk/resources/messages/messages.py b/src/mobilerun_sdk/resources/messages/messages.py
index 2e5f30b6..49cc99a2 100644
--- a/src/mobilerun_sdk/resources/messages/messages.py
+++ b/src/mobilerun_sdk/resources/messages/messages.py
@@ -76,12 +76,9 @@ def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MessageListResponse:
- """Lists the caller's own SMS messages, newest first.
-
- Supports filtering by
- direction, esimId, numberId, status, peerNumber (substring search, min 3
- characters), and peerKey (exact thread match). Each row includes its canonical
- thread key (`peerKey`).
+ """
+ Lists SMS messages newest first, with filters for direction, eSIM, phone number,
+ status, and conversation.
Args:
extra_headers: Send extra headers
@@ -162,12 +159,9 @@ async def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> MessageListResponse:
- """Lists the caller's own SMS messages, newest first.
-
- Supports filtering by
- direction, esimId, numberId, status, peerNumber (substring search, min 3
- characters), and peerKey (exact thread match). Each row includes its canonical
- thread key (`peerKey`).
+ """
+ Lists SMS messages newest first, with filters for direction, eSIM, phone number,
+ status, and conversation.
Args:
extra_headers: Send extra headers
diff --git a/src/mobilerun_sdk/resources/numbers/numbers.py b/src/mobilerun_sdk/resources/numbers/numbers.py
index 7b39353f..76972e69 100644
--- a/src/mobilerun_sdk/resources/numbers/numbers.py
+++ b/src/mobilerun_sdk/resources/numbers/numbers.py
@@ -7,7 +7,7 @@
import httpx
-from ...types import number_list_params, number_create_params, number_update_params
+from ...types import number_list_params, number_create_params, number_update_params, number_capacity_params
from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
from ..._utils import path_template, maybe_transform, strip_not_given, async_maybe_transform
from .messages import (
@@ -31,6 +31,7 @@
from ...types.number_create_response import NumberCreateResponse
from ...types.number_delete_response import NumberDeleteResponse
from ...types.number_update_response import NumberUpdateResponse
+from ...types.number_capacity_response import NumberCapacityResponse
from ...types.number_purposes_response import NumberPurposesResponse
from ...types.number_retrieve_response import NumberRetrieveResponse
from ...types.number_countries_response import NumberCountriesResponse
@@ -65,7 +66,7 @@ def with_streaming_response(self) -> NumbersResourceWithStreamingResponse:
def create(
self,
*,
- billing_preference: Literal["included", "rent"] | Omit = omit,
+ billing_preference: Literal["included", "included_only", "rent"] | Omit = omit,
country: str | Omit = omit,
label: Optional[str] | Omit = omit,
purpose: str | Omit = omit,
@@ -77,24 +78,23 @@ def create(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> NumberCreateResponse:
- """Starts a Mobilerun Phone purchase for the authenticated owner.
+ """Starts a phone-number purchase.
- Accepted requests
- always return the same asynchronous envelope; poll GET /numbers/phones/{id} for
- its business state. `purpose` and `country` are mutually exclusive.
+ Poll the returned phone number for status
+ updates. `purpose` and `country` cannot be combined.
Args:
- billing_preference: Prefer a free package seat ('included', default) or force the paid checkout
- ('rent')
+ billing_preference: Use included capacity when available, require included capacity without paid
+ fallback (included_only), or start a paid checkout (rent).
- country: Optional ISO 3166-1 alpha-2 country code from GET /numbers/countries. Cannot be
- combined with `purpose`.
+ country: Optional ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries.
+ Cannot be combined with `purpose`.
label: User-defined display label — NFC-normalized, up to 100 GRAPHEMES (not UTF-16
code units; an emoji/flag may span several). Display-only, never used for
routing. Also seeds the billing entity name at purchase.
- purpose: Optional Mobilerun Phone purpose slug from GET /numbers/purposes.
+ purpose: Optional purpose from GET /numbers/phones/purposes.
idempotency_key: Optional request idempotency key.
@@ -169,13 +169,10 @@ def update(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> NumberUpdateResponse:
- """Updates the phone number's user-defined display label.
+ """Updates the display label.
- Omitting `label` leaves
- it unchanged; setting it to null or an empty string clears it. The label is
- capped at 100 characters, is display-only, and never affects routing. It also
- seeds the billing entity name when set at purchase time; a later change here
- does not rename the already-created billing entity.
+ Omitting `label` leaves it unchanged; null or an
+ empty string clears it.
Args:
label: User-defined display label — NFC-normalized, up to 100 GRAPHEMES (not UTF-16
@@ -214,8 +211,7 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> NumberListResponse:
"""
- Lists phone numbers owned by the authenticated user — both BYO (`user`) and
- provisioned (`mobilerun`) numbers.
+ Lists the caller's phone numbers.
Args:
extra_headers: Send extra headers
@@ -255,25 +251,10 @@ def delete(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> NumberDeleteResponse:
- """Cancels a Mobilerun Phone.
-
- The outcome depends on the number's current state:
-
- - If the number is still awaiting payment and no payment for it is currently
- being processed, the checkout is closed immediately and the number is retired.
- - If the number is on the standard paid plan and already paid and in service,
- cancellation is scheduled for the end of the current billing period rather
- than taking effect immediately. The number stays usable through the period
- already paid for, with no partial refund. Calling this again while a
- cancellation is already scheduled is a no-op that returns the same result. The
- response's `state` reflects this as `cancel_scheduled` with
- `cancelAtPeriodEnd: true`; `currentPeriodEnd` is populated once billing
- confirms the cancellation.
-
- Any other state (already refunding, a permanent billing failure, a payment
- currently being processed, an included-plan number, or a non-hosted/BYO number)
- returns 409 `not_cancellable`. Returns 404 if the number doesn't exist or isn't
- owned by the caller.
+ """
+ Cancels a pending purchase or schedules cancellation of an active paid phone
+ number. Repeating a scheduled cancellation is safe. Returns 409 when
+ cancellation is not available.
Args:
extra_headers: Send extra headers
@@ -294,6 +275,45 @@ def delete(
cast_to=NumberDeleteResponse,
)
+ def capacity(
+ self,
+ *,
+ country: 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,
+ ) -> NumberCapacityResponse:
+ """Returns included phone capacity for a country.
+
+ Creating a phone is
+ authoritative.
+
+ Args:
+ country: ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries.
+
+ 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(
+ "/numbers/phones/capacity",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform({"country": country}, number_capacity_params.NumberCapacityParams),
+ ),
+ cast_to=NumberCapacityResponse,
+ )
+
def countries(
self,
*,
@@ -304,10 +324,7 @@ def countries(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> NumberCountriesResponse:
- """
- Lists the countries currently offered for a dedicated Mobilerun Phone, with live
- stock status. Pass `country` as the `country` field on POST /numbers/phones.
- """
+ """Lists available countries and current phone-number availability."""
return self._get(
"/numbers/phones/countries",
options=make_request_options(
@@ -363,7 +380,7 @@ def with_streaming_response(self) -> AsyncNumbersResourceWithStreamingResponse:
async def create(
self,
*,
- billing_preference: Literal["included", "rent"] | Omit = omit,
+ billing_preference: Literal["included", "included_only", "rent"] | Omit = omit,
country: str | Omit = omit,
label: Optional[str] | Omit = omit,
purpose: str | Omit = omit,
@@ -375,24 +392,23 @@ async def create(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> NumberCreateResponse:
- """Starts a Mobilerun Phone purchase for the authenticated owner.
+ """Starts a phone-number purchase.
- Accepted requests
- always return the same asynchronous envelope; poll GET /numbers/phones/{id} for
- its business state. `purpose` and `country` are mutually exclusive.
+ Poll the returned phone number for status
+ updates. `purpose` and `country` cannot be combined.
Args:
- billing_preference: Prefer a free package seat ('included', default) or force the paid checkout
- ('rent')
+ billing_preference: Use included capacity when available, require included capacity without paid
+ fallback (included_only), or start a paid checkout (rent).
- country: Optional ISO 3166-1 alpha-2 country code from GET /numbers/countries. Cannot be
- combined with `purpose`.
+ country: Optional ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries.
+ Cannot be combined with `purpose`.
label: User-defined display label — NFC-normalized, up to 100 GRAPHEMES (not UTF-16
code units; an emoji/flag may span several). Display-only, never used for
routing. Also seeds the billing entity name at purchase.
- purpose: Optional Mobilerun Phone purpose slug from GET /numbers/purposes.
+ purpose: Optional purpose from GET /numbers/phones/purposes.
idempotency_key: Optional request idempotency key.
@@ -467,13 +483,10 @@ async def update(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> NumberUpdateResponse:
- """Updates the phone number's user-defined display label.
+ """Updates the display label.
- Omitting `label` leaves
- it unchanged; setting it to null or an empty string clears it. The label is
- capped at 100 characters, is display-only, and never affects routing. It also
- seeds the billing entity name when set at purchase time; a later change here
- does not rename the already-created billing entity.
+ Omitting `label` leaves it unchanged; null or an
+ empty string clears it.
Args:
label: User-defined display label — NFC-normalized, up to 100 GRAPHEMES (not UTF-16
@@ -512,8 +525,7 @@ async def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> NumberListResponse:
"""
- Lists phone numbers owned by the authenticated user — both BYO (`user`) and
- provisioned (`mobilerun`) numbers.
+ Lists the caller's phone numbers.
Args:
extra_headers: Send extra headers
@@ -553,25 +565,10 @@ async def delete(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> NumberDeleteResponse:
- """Cancels a Mobilerun Phone.
-
- The outcome depends on the number's current state:
-
- - If the number is still awaiting payment and no payment for it is currently
- being processed, the checkout is closed immediately and the number is retired.
- - If the number is on the standard paid plan and already paid and in service,
- cancellation is scheduled for the end of the current billing period rather
- than taking effect immediately. The number stays usable through the period
- already paid for, with no partial refund. Calling this again while a
- cancellation is already scheduled is a no-op that returns the same result. The
- response's `state` reflects this as `cancel_scheduled` with
- `cancelAtPeriodEnd: true`; `currentPeriodEnd` is populated once billing
- confirms the cancellation.
-
- Any other state (already refunding, a permanent billing failure, a payment
- currently being processed, an included-plan number, or a non-hosted/BYO number)
- returns 409 `not_cancellable`. Returns 404 if the number doesn't exist or isn't
- owned by the caller.
+ """
+ Cancels a pending purchase or schedules cancellation of an active paid phone
+ number. Repeating a scheduled cancellation is safe. Returns 409 when
+ cancellation is not available.
Args:
extra_headers: Send extra headers
@@ -592,6 +589,45 @@ async def delete(
cast_to=NumberDeleteResponse,
)
+ async def capacity(
+ self,
+ *,
+ country: 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,
+ ) -> NumberCapacityResponse:
+ """Returns included phone capacity for a country.
+
+ Creating a phone is
+ authoritative.
+
+ Args:
+ country: ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries.
+
+ 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 await self._get(
+ "/numbers/phones/capacity",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform({"country": country}, number_capacity_params.NumberCapacityParams),
+ ),
+ cast_to=NumberCapacityResponse,
+ )
+
async def countries(
self,
*,
@@ -602,10 +638,7 @@ async def countries(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> NumberCountriesResponse:
- """
- Lists the countries currently offered for a dedicated Mobilerun Phone, with live
- stock status. Pass `country` as the `country` field on POST /numbers/phones.
- """
+ """Lists available countries and current phone-number availability."""
return await self._get(
"/numbers/phones/countries",
options=make_request_options(
@@ -653,6 +686,9 @@ def __init__(self, numbers: NumbersResource) -> None:
self.delete = to_raw_response_wrapper(
numbers.delete,
)
+ self.capacity = to_raw_response_wrapper(
+ numbers.capacity,
+ )
self.countries = to_raw_response_wrapper(
numbers.countries,
)
@@ -684,6 +720,9 @@ def __init__(self, numbers: AsyncNumbersResource) -> None:
self.delete = async_to_raw_response_wrapper(
numbers.delete,
)
+ self.capacity = async_to_raw_response_wrapper(
+ numbers.capacity,
+ )
self.countries = async_to_raw_response_wrapper(
numbers.countries,
)
@@ -715,6 +754,9 @@ def __init__(self, numbers: NumbersResource) -> None:
self.delete = to_streamed_response_wrapper(
numbers.delete,
)
+ self.capacity = to_streamed_response_wrapper(
+ numbers.capacity,
+ )
self.countries = to_streamed_response_wrapper(
numbers.countries,
)
@@ -746,6 +788,9 @@ def __init__(self, numbers: AsyncNumbersResource) -> None:
self.delete = async_to_streamed_response_wrapper(
numbers.delete,
)
+ self.capacity = async_to_streamed_response_wrapper(
+ numbers.capacity,
+ )
self.countries = async_to_streamed_response_wrapper(
numbers.countries,
)
diff --git a/src/mobilerun_sdk/resources/tasks/tasks.py b/src/mobilerun_sdk/resources/tasks/tasks.py
index e73ca6bb..c7687a78 100644
--- a/src/mobilerun_sdk/resources/tasks/tasks.py
+++ b/src/mobilerun_sdk/resources/tasks/tasks.py
@@ -121,7 +121,10 @@ def list(
page: int | Omit = omit,
page_size: int | Omit = omit,
query: Optional[str] | Omit = omit,
- status: Optional[Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]]
+ source: Optional[Literal["api", "agent"]] | Omit = omit,
+ status: Optional[
+ Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]
+ ]
| 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.
@@ -140,6 +143,8 @@ def list(
query: Search in task description.
+ source: Only tasks created via the API ('api') or spawned by an agent step ('agent').
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -164,6 +169,7 @@ def list(
"page": page,
"page_size": page_size,
"query": query,
+ "source": source,
"status": status,
},
task_list_params.TaskListParams,
@@ -278,7 +284,6 @@ def run(
device_id: str,
task: str,
accessibility: bool | Omit = omit,
- agent_id: int | Omit = omit,
apps: SequenceNotStr[str] | Omit = omit,
continue_on_failure: bool | Omit = omit,
credentials: Iterable[task_run_params.Credential] | Omit = omit,
@@ -290,8 +295,10 @@ def run(
memory_namespace: str | Omit = omit,
output_schema: Optional[Dict[str, object]] | Omit = omit,
reasoning: bool | Omit = omit,
+ recording_enabled: bool | Omit = omit,
stealth: bool | Omit = omit,
subagent_model: str | Omit = omit,
+ system_prompt: Optional[str] | Omit = omit,
temperature: float | Omit = omit,
vision: bool | Omit = omit,
vpn_country: Optional[Literal["US", "BR", "FR", "DE", "IN", "JP", "KR", "ZA"]] | Omit = omit,
@@ -313,12 +320,19 @@ def run(
display_id: The display ID of the device to run the task on.
- llm_model: The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash')
+ llm_model: The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna')
memory_namespace: Memory namespace for cross-task personalization
+ recording_enabled: Record device video for the whole task and persist a retrievable reference
+
subagent_model: LLM model used by sub-agent roles: executor, app_opener, structured_output
+ system_prompt: Optional custom behavioral overlay applied on top of the agent's default system
+ prompts. Never echoed back in responses or errors.
+
+ temperature: Deprecated and ignored. Sampling behavior is controlled by the model provider.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -335,7 +349,6 @@ def run(
"device_id": device_id,
"task": task,
"accessibility": accessibility,
- "agent_id": agent_id,
"apps": apps,
"continue_on_failure": continue_on_failure,
"credentials": credentials,
@@ -347,8 +360,10 @@ def run(
"memory_namespace": memory_namespace,
"output_schema": output_schema,
"reasoning": reasoning,
+ "recording_enabled": recording_enabled,
"stealth": stealth,
"subagent_model": subagent_model,
+ "system_prompt": system_prompt,
"temperature": temperature,
"vision": vision,
"vpn_country": vpn_country,
@@ -367,7 +382,6 @@ def run_streamed(
device_id: str,
task: str,
accessibility: bool | Omit = omit,
- agent_id: int | Omit = omit,
apps: SequenceNotStr[str] | Omit = omit,
continue_on_failure: bool | Omit = omit,
credentials: Iterable[task_run_streamed_params.Credential] | Omit = omit,
@@ -379,8 +393,10 @@ def run_streamed(
memory_namespace: str | Omit = omit,
output_schema: Optional[Dict[str, object]] | Omit = omit,
reasoning: bool | Omit = omit,
+ recording_enabled: bool | Omit = omit,
stealth: bool | Omit = omit,
subagent_model: str | Omit = omit,
+ system_prompt: Optional[str] | Omit = omit,
temperature: float | Omit = omit,
vision: bool | Omit = omit,
vpn_country: Optional[Literal["US", "BR", "FR", "DE", "IN", "JP", "KR", "ZA"]] | Omit = omit,
@@ -400,12 +416,19 @@ def run_streamed(
display_id: The display ID of the device to run the task on.
- llm_model: The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash')
+ llm_model: The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna')
memory_namespace: Memory namespace for cross-task personalization
+ recording_enabled: Record device video for the whole task and persist a retrievable reference
+
subagent_model: LLM model used by sub-agent roles: executor, app_opener, structured_output
+ system_prompt: Optional custom behavioral overlay applied on top of the agent's default system
+ prompts. Never echoed back in responses or errors.
+
+ temperature: Deprecated and ignored. Sampling behavior is controlled by the model provider.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -421,7 +444,6 @@ def run_streamed(
"device_id": device_id,
"task": task,
"accessibility": accessibility,
- "agent_id": agent_id,
"apps": apps,
"continue_on_failure": continue_on_failure,
"credentials": credentials,
@@ -433,8 +455,10 @@ def run_streamed(
"memory_namespace": memory_namespace,
"output_schema": output_schema,
"reasoning": reasoning,
+ "recording_enabled": recording_enabled,
"stealth": stealth,
"subagent_model": subagent_model,
+ "system_prompt": system_prompt,
"temperature": temperature,
"vision": vision,
"vpn_country": vpn_country,
@@ -597,7 +621,10 @@ async def list(
page: int | Omit = omit,
page_size: int | Omit = omit,
query: Optional[str] | Omit = omit,
- status: Optional[Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]]
+ source: Optional[Literal["api", "agent"]] | Omit = omit,
+ status: Optional[
+ Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]
+ ]
| 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.
@@ -616,6 +643,8 @@ async def list(
query: Search in task description.
+ source: Only tasks created via the API ('api') or spawned by an agent step ('agent').
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -640,6 +669,7 @@ async def list(
"page": page,
"page_size": page_size,
"query": query,
+ "source": source,
"status": status,
},
task_list_params.TaskListParams,
@@ -754,7 +784,6 @@ async def run(
device_id: str,
task: str,
accessibility: bool | Omit = omit,
- agent_id: int | Omit = omit,
apps: SequenceNotStr[str] | Omit = omit,
continue_on_failure: bool | Omit = omit,
credentials: Iterable[task_run_params.Credential] | Omit = omit,
@@ -766,8 +795,10 @@ async def run(
memory_namespace: str | Omit = omit,
output_schema: Optional[Dict[str, object]] | Omit = omit,
reasoning: bool | Omit = omit,
+ recording_enabled: bool | Omit = omit,
stealth: bool | Omit = omit,
subagent_model: str | Omit = omit,
+ system_prompt: Optional[str] | Omit = omit,
temperature: float | Omit = omit,
vision: bool | Omit = omit,
vpn_country: Optional[Literal["US", "BR", "FR", "DE", "IN", "JP", "KR", "ZA"]] | Omit = omit,
@@ -789,12 +820,19 @@ async def run(
display_id: The display ID of the device to run the task on.
- llm_model: The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash')
+ llm_model: The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna')
memory_namespace: Memory namespace for cross-task personalization
+ recording_enabled: Record device video for the whole task and persist a retrievable reference
+
subagent_model: LLM model used by sub-agent roles: executor, app_opener, structured_output
+ system_prompt: Optional custom behavioral overlay applied on top of the agent's default system
+ prompts. Never echoed back in responses or errors.
+
+ temperature: Deprecated and ignored. Sampling behavior is controlled by the model provider.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -811,7 +849,6 @@ async def run(
"device_id": device_id,
"task": task,
"accessibility": accessibility,
- "agent_id": agent_id,
"apps": apps,
"continue_on_failure": continue_on_failure,
"credentials": credentials,
@@ -823,8 +860,10 @@ async def run(
"memory_namespace": memory_namespace,
"output_schema": output_schema,
"reasoning": reasoning,
+ "recording_enabled": recording_enabled,
"stealth": stealth,
"subagent_model": subagent_model,
+ "system_prompt": system_prompt,
"temperature": temperature,
"vision": vision,
"vpn_country": vpn_country,
@@ -843,7 +882,6 @@ async def run_streamed(
device_id: str,
task: str,
accessibility: bool | Omit = omit,
- agent_id: int | Omit = omit,
apps: SequenceNotStr[str] | Omit = omit,
continue_on_failure: bool | Omit = omit,
credentials: Iterable[task_run_streamed_params.Credential] | Omit = omit,
@@ -855,8 +893,10 @@ async def run_streamed(
memory_namespace: str | Omit = omit,
output_schema: Optional[Dict[str, object]] | Omit = omit,
reasoning: bool | Omit = omit,
+ recording_enabled: bool | Omit = omit,
stealth: bool | Omit = omit,
subagent_model: str | Omit = omit,
+ system_prompt: Optional[str] | Omit = omit,
temperature: float | Omit = omit,
vision: bool | Omit = omit,
vpn_country: Optional[Literal["US", "BR", "FR", "DE", "IN", "JP", "KR", "ZA"]] | Omit = omit,
@@ -876,12 +916,19 @@ async def run_streamed(
display_id: The display ID of the device to run the task on.
- llm_model: The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash')
+ llm_model: The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna')
memory_namespace: Memory namespace for cross-task personalization
+ recording_enabled: Record device video for the whole task and persist a retrievable reference
+
subagent_model: LLM model used by sub-agent roles: executor, app_opener, structured_output
+ system_prompt: Optional custom behavioral overlay applied on top of the agent's default system
+ prompts. Never echoed back in responses or errors.
+
+ temperature: Deprecated and ignored. Sampling behavior is controlled by the model provider.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -897,7 +944,6 @@ async def run_streamed(
"device_id": device_id,
"task": task,
"accessibility": accessibility,
- "agent_id": agent_id,
"apps": apps,
"continue_on_failure": continue_on_failure,
"credentials": credentials,
@@ -909,8 +955,10 @@ async def run_streamed(
"memory_namespace": memory_namespace,
"output_schema": output_schema,
"reasoning": reasoning,
+ "recording_enabled": recording_enabled,
"stealth": stealth,
"subagent_model": subagent_model,
+ "system_prompt": system_prompt,
"temperature": temperature,
"vision": vision,
"vpn_country": vpn_country,
diff --git a/src/mobilerun_sdk/resources/workflows/flows/actions.py b/src/mobilerun_sdk/resources/workflows/flows/actions.py
index 0fd2150d..26ca8773 100644
--- a/src/mobilerun_sdk/resources/workflows/flows/actions.py
+++ b/src/mobilerun_sdk/resources/workflows/flows/actions.py
@@ -91,6 +91,7 @@ def add(
name_override: str | Omit = omit,
overrides: Optional[action_add_params.Overrides] | Omit = omit,
parent_flow_action_id: Optional[str] | Omit = omit,
+ recording_enabled: 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,
@@ -126,6 +127,7 @@ def add(
"name_override": name_override,
"overrides": overrides,
"parent_flow_action_id": parent_flow_action_id,
+ "recording_enabled": recording_enabled,
},
action_add_params.ActionAddParams,
),
@@ -277,6 +279,7 @@ async def add(
name_override: str | Omit = omit,
overrides: Optional[action_add_params.Overrides] | Omit = omit,
parent_flow_action_id: Optional[str] | Omit = omit,
+ recording_enabled: 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,
@@ -312,6 +315,7 @@ async def add(
"name_override": name_override,
"overrides": overrides,
"parent_flow_action_id": parent_flow_action_id,
+ "recording_enabled": recording_enabled,
},
action_add_params.ActionAddParams,
),
diff --git a/src/mobilerun_sdk/resources/workflows/flows/flows.py b/src/mobilerun_sdk/resources/workflows/flows/flows.py
index db390fcc..1faf5913 100644
--- a/src/mobilerun_sdk/resources/workflows/flows/flows.py
+++ b/src/mobilerun_sdk/resources/workflows/flows/flows.py
@@ -40,6 +40,7 @@
from ....types.workflows.flow_update_response import FlowUpdateResponse
from ....types.workflows.flow_dry_run_response import FlowDryRunResponse
from ....types.workflows.flow_unblock_response import FlowUnblockResponse
+from ....types.workflows.flow_capacity_response import FlowCapacityResponse
from ....types.workflows.flow_retrieve_response import FlowRetrieveResponse
from ....types.workflows.flow_list_repairs_response import FlowListRepairsResponse
@@ -86,6 +87,7 @@ def create(
notify_on_success: bool | Omit = omit,
notify_webhook_id: Optional[str] | Omit = omit,
recording_enabled: bool | Omit = omit,
+ recording_policy: flow_create_params.RecordingPolicy | Omit = omit,
self_healing_enabled: bool | Omit = omit,
self_healing_max_attempts: int | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -102,6 +104,9 @@ def create(
success or failure.
Args:
+ recording_enabled: Deprecated compatibility field. true maps to recordingPolicy.mode="flow"; false
+ maps to "off".
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -127,6 +132,7 @@ def create(
"notify_on_success": notify_on_success,
"notify_webhook_id": notify_webhook_id,
"recording_enabled": recording_enabled,
+ "recording_policy": recording_policy,
"self_healing_enabled": self_healing_enabled,
"self_healing_max_attempts": self_healing_max_attempts,
},
@@ -182,11 +188,13 @@ def update(
device_ids: SequenceNotStr[str] | Omit = omit,
enabled: bool | Omit = omit,
health_monitoring_enabled: bool | Omit = omit,
+ lifecycle_status: Literal["enabled", "disabled"] | Omit = omit,
name: str | Omit = omit,
notify_on_failure: bool | Omit = omit,
notify_on_success: bool | Omit = omit,
notify_webhook_id: Optional[str] | Omit = omit,
recording_enabled: bool | Omit = omit,
+ recording_policy: flow_update_params.RecordingPolicy | Omit = omit,
self_healing_enabled: bool | Omit = omit,
self_healing_max_attempts: int | Omit = omit,
trigger_id: str | Omit = omit,
@@ -204,6 +212,11 @@ def update(
does not exist.
Args:
+ lifecycle_status: Set the visible agent lifecycle. Archive remains available only through DELETE.
+
+ recording_enabled: Deprecated compatibility field. true maps to recordingPolicy.mode="flow"; false
+ maps to "off".
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -224,11 +237,13 @@ def update(
"device_ids": device_ids,
"enabled": enabled,
"health_monitoring_enabled": health_monitoring_enabled,
+ "lifecycle_status": lifecycle_status,
"name": name,
"notify_on_failure": notify_on_failure,
"notify_on_success": notify_on_success,
"notify_webhook_id": notify_webhook_id,
"recording_enabled": recording_enabled,
+ "recording_policy": recording_policy,
"self_healing_enabled": self_healing_enabled,
"self_healing_max_attempts": self_healing_max_attempts,
"trigger_id": trigger_id,
@@ -318,9 +333,10 @@ def delete(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> FlowDeleteResponse:
- """Delete a flow by its ID.
+ """Terminally archive a flow by its ID.
- Returns 404 if no flow matches.
+ Archived flows cannot be restored and are
+ hidden from customer reads. Repeating the request is idempotent for the owner.
Args:
extra_headers: Send extra headers
@@ -341,6 +357,30 @@ def delete(
cast_to=FlowDeleteResponse,
)
+ def capacity(
+ self,
+ *,
+ # 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,
+ ) -> FlowCapacityResponse:
+ """
+ Returns an owner-scoped snapshot of finite included workflow-agent capacity
+ after locally stored enabled and disabled agents. Available only while slot
+ enforcement is enabled; otherwise returns 503. This is advisory; create and
+ clone perform authoritative admission under an owner lock.
+ """
+ return self._get(
+ "/flows/capacity",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowCapacityResponse,
+ )
+
def clone(
self,
flow_id: str,
@@ -543,6 +583,7 @@ async def create(
notify_on_success: bool | Omit = omit,
notify_webhook_id: Optional[str] | Omit = omit,
recording_enabled: bool | Omit = omit,
+ recording_policy: flow_create_params.RecordingPolicy | Omit = omit,
self_healing_enabled: bool | Omit = omit,
self_healing_max_attempts: int | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -559,6 +600,9 @@ async def create(
success or failure.
Args:
+ recording_enabled: Deprecated compatibility field. true maps to recordingPolicy.mode="flow"; false
+ maps to "off".
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -584,6 +628,7 @@ async def create(
"notify_on_success": notify_on_success,
"notify_webhook_id": notify_webhook_id,
"recording_enabled": recording_enabled,
+ "recording_policy": recording_policy,
"self_healing_enabled": self_healing_enabled,
"self_healing_max_attempts": self_healing_max_attempts,
},
@@ -639,11 +684,13 @@ async def update(
device_ids: SequenceNotStr[str] | Omit = omit,
enabled: bool | Omit = omit,
health_monitoring_enabled: bool | Omit = omit,
+ lifecycle_status: Literal["enabled", "disabled"] | Omit = omit,
name: str | Omit = omit,
notify_on_failure: bool | Omit = omit,
notify_on_success: bool | Omit = omit,
notify_webhook_id: Optional[str] | Omit = omit,
recording_enabled: bool | Omit = omit,
+ recording_policy: flow_update_params.RecordingPolicy | Omit = omit,
self_healing_enabled: bool | Omit = omit,
self_healing_max_attempts: int | Omit = omit,
trigger_id: str | Omit = omit,
@@ -661,6 +708,11 @@ async def update(
does not exist.
Args:
+ lifecycle_status: Set the visible agent lifecycle. Archive remains available only through DELETE.
+
+ recording_enabled: Deprecated compatibility field. true maps to recordingPolicy.mode="flow"; false
+ maps to "off".
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -681,11 +733,13 @@ async def update(
"device_ids": device_ids,
"enabled": enabled,
"health_monitoring_enabled": health_monitoring_enabled,
+ "lifecycle_status": lifecycle_status,
"name": name,
"notify_on_failure": notify_on_failure,
"notify_on_success": notify_on_success,
"notify_webhook_id": notify_webhook_id,
"recording_enabled": recording_enabled,
+ "recording_policy": recording_policy,
"self_healing_enabled": self_healing_enabled,
"self_healing_max_attempts": self_healing_max_attempts,
"trigger_id": trigger_id,
@@ -775,9 +829,10 @@ async def delete(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> FlowDeleteResponse:
- """Delete a flow by its ID.
+ """Terminally archive a flow by its ID.
- Returns 404 if no flow matches.
+ Archived flows cannot be restored and are
+ hidden from customer reads. Repeating the request is idempotent for the owner.
Args:
extra_headers: Send extra headers
@@ -798,6 +853,30 @@ async def delete(
cast_to=FlowDeleteResponse,
)
+ async def capacity(
+ self,
+ *,
+ # 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,
+ ) -> FlowCapacityResponse:
+ """
+ Returns an owner-scoped snapshot of finite included workflow-agent capacity
+ after locally stored enabled and disabled agents. Available only while slot
+ enforcement is enabled; otherwise returns 503. This is advisory; create and
+ clone perform authoritative admission under an owner lock.
+ """
+ return await self._get(
+ "/flows/capacity",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowCapacityResponse,
+ )
+
async def clone(
self,
flow_id: str,
@@ -979,6 +1058,9 @@ def __init__(self, flows: FlowsResource) -> None:
self.delete = to_raw_response_wrapper(
flows.delete,
)
+ self.capacity = to_raw_response_wrapper(
+ flows.capacity,
+ )
self.clone = to_raw_response_wrapper(
flows.clone,
)
@@ -1016,6 +1098,9 @@ def __init__(self, flows: AsyncFlowsResource) -> None:
self.delete = async_to_raw_response_wrapper(
flows.delete,
)
+ self.capacity = async_to_raw_response_wrapper(
+ flows.capacity,
+ )
self.clone = async_to_raw_response_wrapper(
flows.clone,
)
@@ -1053,6 +1138,9 @@ def __init__(self, flows: FlowsResource) -> None:
self.delete = to_streamed_response_wrapper(
flows.delete,
)
+ self.capacity = to_streamed_response_wrapper(
+ flows.capacity,
+ )
self.clone = to_streamed_response_wrapper(
flows.clone,
)
@@ -1090,6 +1178,9 @@ def __init__(self, flows: AsyncFlowsResource) -> None:
self.delete = async_to_streamed_response_wrapper(
flows.delete,
)
+ self.capacity = async_to_streamed_response_wrapper(
+ flows.capacity,
+ )
self.clone = async_to_streamed_response_wrapper(
flows.clone,
)
diff --git a/src/mobilerun_sdk/types/__init__.py b/src/mobilerun_sdk/types/__init__.py
index 310d2f0f..7e1d124c 100644
--- a/src/mobilerun_sdk/types/__init__.py
+++ b/src/mobilerun_sdk/types/__init__.py
@@ -17,26 +17,17 @@
)
from .app_list_params import AppListParams as AppListParams
from .task_run_params import TaskRunParams as TaskRunParams
-from .esim_list_params import EsimListParams as EsimListParams
-from .file_list_params import FileListParams as FileListParams
from .task_list_params import TaskListParams as TaskListParams
from .app_list_response import AppListResponse as AppListResponse
from .proxy_list_params import ProxyListParams as ProxyListParams
from .task_run_response import TaskRunResponse as TaskRunResponse
from .device_list_params import DeviceListParams as DeviceListParams
-from .esim_create_params import EsimCreateParams as EsimCreateParams
-from .esim_import_params import EsimImportParams as EsimImportParams
-from .esim_list_response import EsimListResponse as EsimListResponse
-from .esim_update_params import EsimUpdateParams as EsimUpdateParams
-from .file_list_response import FileListResponse as FileListResponse
-from .file_update_params import FileUpdateParams as FileUpdateParams
from .mailbox_otp_params import MailboxOtpParams as MailboxOtpParams
from .number_list_params import NumberListParams as NumberListParams
from .task_list_response import TaskListResponse as TaskListResponse
from .task_stop_response import TaskStopResponse as TaskStopResponse
from .app_delete_response import AppDeleteResponse as AppDeleteResponse
from .carrier_list_params import CarrierListParams as CarrierListParams
-from .esim_install_params import EsimInstallParams as EsimInstallParams
from .mailbox_list_params import MailboxListParams as MailboxListParams
from .message_list_params import MessageListParams as MessageListParams
from .model_list_response import ModelListResponse as ModelListResponse
@@ -48,12 +39,7 @@
from .webhook_list_params import WebhookListParams as WebhookListParams
from .device_create_params import DeviceCreateParams as DeviceCreateParams
from .device_list_response import DeviceListResponse as DeviceListResponse
-from .esim_create_response import EsimCreateResponse as EsimCreateResponse
-from .esim_import_response import EsimImportResponse as EsimImportResponse
-from .esim_selector_params import EsimSelectorParams as EsimSelectorParams
-from .esim_update_response import EsimUpdateResponse as EsimUpdateResponse
from .file_delete_response import FileDeleteResponse as FileDeleteResponse
-from .file_update_response import FileUpdateResponse as FileUpdateResponse
from .mailbox_otp_response import MailboxOtpResponse as MailboxOtpResponse
from .number_create_params import NumberCreateParams as NumberCreateParams
from .number_list_response import NumberListResponse as NumberListResponse
@@ -65,8 +51,6 @@
from .carrier_lookup_params import CarrierLookupParams as CarrierLookupParams
from .carrier_update_params import CarrierUpdateParams as CarrierUpdateParams
from .device_count_response import DeviceCountResponse as DeviceCountResponse
-from .esim_install_response import EsimInstallResponse as EsimInstallResponse
-from .file_confirm_response import FileConfirmResponse as FileConfirmResponse
from .mailbox_create_params import MailboxCreateParams as MailboxCreateParams
from .mailbox_list_response import MailboxListResponse as MailboxListResponse
from .mailbox_update_params import MailboxUpdateParams as MailboxUpdateParams
@@ -84,11 +68,9 @@
from .credential_list_params import CredentialListParams as CredentialListParams
from .device_create_response import DeviceCreateResponse as DeviceCreateResponse
from .device_set_name_params import DeviceSetNameParams as DeviceSetNameParams
-from .esim_capacity_response import EsimCapacityResponse as EsimCapacityResponse
-from .esim_retrieve_response import EsimRetrieveResponse as EsimRetrieveResponse
-from .esim_selector_response import EsimSelectorResponse as EsimSelectorResponse
from .file_upload_url_params import FileUploadURLParams as FileUploadURLParams
from .mailbox_restart_params import MailboxRestartParams as MailboxRestartParams
+from .number_capacity_params import NumberCapacityParams as NumberCapacityParams
from .number_create_response import NumberCreateResponse as NumberCreateResponse
from .number_delete_response import NumberDeleteResponse as NumberDeleteResponse
from .number_update_response import NumberUpdateResponse as NumberUpdateResponse
@@ -114,6 +96,7 @@
from .device_set_name_response import DeviceSetNameResponse as DeviceSetNameResponse
from .file_upload_url_response import FileUploadURLResponse as FileUploadURLResponse
from .mailbox_restart_response import MailboxRestartResponse as MailboxRestartResponse
+from .number_capacity_response import NumberCapacityResponse as NumberCapacityResponse
from .number_purposes_response import NumberPurposesResponse as NumberPurposesResponse
from .number_retrieve_response import NumberRetrieveResponse as NumberRetrieveResponse
from .task_get_status_response import TaskGetStatusResponse as TaskGetStatusResponse
@@ -134,11 +117,9 @@
from .app_confirm_upload_response import AppConfirmUploadResponse as AppConfirmUploadResponse
from .app_event_retrieve_response import AppEventRetrieveResponse as AppEventRetrieveResponse
from .device_fingerprint_response import DeviceFingerprintResponse as DeviceFingerprintResponse
-from .esim_install_status_response import EsimInstallStatusResponse as EsimInstallStatusResponse
from .file_cancel_pending_response import FileCancelPendingResponse as FileCancelPendingResponse
from .task_get_trajectory_response import TaskGetTrajectoryResponse as TaskGetTrajectoryResponse
from .webhook_event_types_response import WebhookEventTypesResponse as WebhookEventTypesResponse
-from .esim_confirm_payment_response import EsimConfirmPaymentResponse as EsimConfirmPaymentResponse
from .notification_catalog_response import NotificationCatalogResponse as NotificationCatalogResponse
from .webhook_rotate_secret_response import WebhookRotateSecretResponse as WebhookRotateSecretResponse
from .webhook_test_delivery_response import WebhookTestDeliveryResponse as WebhookTestDeliveryResponse
diff --git a/src/mobilerun_sdk/types/app_storage_usage_response.py b/src/mobilerun_sdk/types/app_storage_usage_response.py
index f1c225ec..f9dd47c4 100644
--- a/src/mobilerun_sdk/types/app_storage_usage_response.py
+++ b/src/mobilerun_sdk/types/app_storage_usage_response.py
@@ -9,12 +9,19 @@
class Data(BaseModel):
available_bytes: float = FieldInfo(alias="availableBytes")
- """Remaining bytes — the reliable maximum size for the next upload.
+ """Remaining bytes — the reliable maximum TOTAL size for the next upload.
Advisory snapshot: the quota is enforced under a lock at confirm, so concurrent
uploads may reduce actual headroom.
"""
+ max_file_bytes: float = FieldInfo(alias="maxFileBytes")
+ """Per-file upload cap in bytes (env.MAX_UPLOAD_FILE_BYTES).
+
+ A single file larger than this is rejected at confirm even when it fits the
+ remaining quota. Source of truth for the client-side per-file limit.
+ """
+
quota_bytes: float = FieldInfo(alias="quotaBytes")
"""Total storage allowance for the user, in bytes"""
diff --git a/src/mobilerun_sdk/types/assistant/conversation_history_response.py b/src/mobilerun_sdk/types/assistant/conversation_history_response.py
index 8288033a..b2f79efc 100644
--- a/src/mobilerun_sdk/types/assistant/conversation_history_response.py
+++ b/src/mobilerun_sdk/types/assistant/conversation_history_response.py
@@ -65,4 +65,6 @@ class ConversationHistoryResponse(BaseModel):
turn_active: bool = FieldInfo(alias="turnActive")
+ last_turn_outcome: Optional[str] = FieldInfo(alias="lastTurnOutcome", default=None)
+
truncated: Optional[bool] = None
diff --git a/src/mobilerun_sdk/types/connect/proxy_buy_params.py b/src/mobilerun_sdk/types/connect/proxy_buy_params.py
index b8147750..8426ebeb 100644
--- a/src/mobilerun_sdk/types/connect/proxy_buy_params.py
+++ b/src/mobilerun_sdk/types/connect/proxy_buy_params.py
@@ -2,7 +2,9 @@
from __future__ import annotations
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
__all__ = ["ProxyBuyParams"]
@@ -12,3 +14,5 @@ class ProxyBuyParams(TypedDict, total=False):
"""ISO 3166-1 alpha-2 country code to provision the proxy in."""
type: Required[Literal["dedicated_residential", "residential", "mobile"]]
+
+ idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")]
diff --git a/src/mobilerun_sdk/types/connect/proxy_buy_response.py b/src/mobilerun_sdk/types/connect/proxy_buy_response.py
index 403a8d80..d512bbef 100644
--- a/src/mobilerun_sdk/types/connect/proxy_buy_response.py
+++ b/src/mobilerun_sdk/types/connect/proxy_buy_response.py
@@ -27,20 +27,23 @@ class ProxyBuyResponse(BaseModel):
port: int
- status: Literal["pending_payment", "provisioning", "active", "cancelling", "ended", "error"]
+ status: Literal["checking", "pending_payment", "provisioning", "active", "cancelling", "ended", "error"]
"""Lifecycle of a proxy.
- A freshly created proxy is `provisioning` — or `pending_payment` until the
- customer completes checkout — and becomes `active` once its upstream is
- assigned. `cancelling` retains full access through the paid period; when the
- subscription expires the proxy is `ended`. `error` marks a failed provisioning
- attempt.
+ A freshly created proxy is `checking` while its billing identity is being
+ resolved — clients should poll until a `paymentUrl` or a later status appears —
+ then `provisioning` — or `pending_payment` until the customer completes checkout
+ — and becomes `active` once its upstream is assigned. `cancelling` retains full
+ access through the paid period; when the subscription expires the proxy is
+ `ended`. `error` marks a failed provisioning attempt.
"""
type: Literal["dedicated_residential", "residential", "mobile"]
username: str
+ billing_mode: Optional[Literal["included", "standalone_paid"]] = FieldInfo(alias="billingMode", default=None)
+
payment_url: Optional[str] = FieldInfo(alias="paymentUrl", default=None)
"""Checkout URL to complete payment while status is `pending_payment`.
diff --git a/src/mobilerun_sdk/types/connect/proxy_list_response.py b/src/mobilerun_sdk/types/connect/proxy_list_response.py
index 26135dca..e68fd457 100644
--- a/src/mobilerun_sdk/types/connect/proxy_list_response.py
+++ b/src/mobilerun_sdk/types/connect/proxy_list_response.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import List
+from typing import List, Optional
from datetime import datetime
from typing_extensions import Literal
@@ -25,20 +25,23 @@ class Item(BaseModel):
port: int
- status: Literal["pending_payment", "provisioning", "active", "cancelling", "ended", "error"]
+ status: Literal["checking", "pending_payment", "provisioning", "active", "cancelling", "ended", "error"]
"""Lifecycle of a proxy.
- A freshly created proxy is `provisioning` — or `pending_payment` until the
- customer completes checkout — and becomes `active` once its upstream is
- assigned. `cancelling` retains full access through the paid period; when the
- subscription expires the proxy is `ended`. `error` marks a failed provisioning
- attempt.
+ A freshly created proxy is `checking` while its billing identity is being
+ resolved — clients should poll until a `paymentUrl` or a later status appears —
+ then `provisioning` — or `pending_payment` until the customer completes checkout
+ — and becomes `active` once its upstream is assigned. `cancelling` retains full
+ access through the paid period; when the subscription expires the proxy is
+ `ended`. `error` marks a failed provisioning attempt.
"""
type: Literal["dedicated_residential", "residential", "mobile"]
username: str
+ billing_mode: Optional[Literal["included", "standalone_paid"]] = FieldInfo(alias="billingMode", default=None)
+
class Pagination(BaseModel):
"""Pagination metadata for a list response."""
diff --git a/src/mobilerun_sdk/types/connect/proxy_retrieve_response.py b/src/mobilerun_sdk/types/connect/proxy_retrieve_response.py
index be8cd872..41014606 100644
--- a/src/mobilerun_sdk/types/connect/proxy_retrieve_response.py
+++ b/src/mobilerun_sdk/types/connect/proxy_retrieve_response.py
@@ -27,20 +27,23 @@ class ProxyRetrieveResponse(BaseModel):
port: int
- status: Literal["pending_payment", "provisioning", "active", "cancelling", "ended", "error"]
+ status: Literal["checking", "pending_payment", "provisioning", "active", "cancelling", "ended", "error"]
"""Lifecycle of a proxy.
- A freshly created proxy is `provisioning` — or `pending_payment` until the
- customer completes checkout — and becomes `active` once its upstream is
- assigned. `cancelling` retains full access through the paid period; when the
- subscription expires the proxy is `ended`. `error` marks a failed provisioning
- attempt.
+ A freshly created proxy is `checking` while its billing identity is being
+ resolved — clients should poll until a `paymentUrl` or a later status appears —
+ then `provisioning` — or `pending_payment` until the customer completes checkout
+ — and becomes `active` once its upstream is assigned. `cancelling` retains full
+ access through the paid period; when the subscription expires the proxy is
+ `ended`. `error` marks a failed provisioning attempt.
"""
type: Literal["dedicated_residential", "residential", "mobile"]
username: str
+ billing_mode: Optional[Literal["included", "standalone_paid"]] = FieldInfo(alias="billingMode", default=None)
+
payment_url: Optional[str] = FieldInfo(alias="paymentUrl", default=None)
"""Checkout URL to complete payment while status is `pending_payment`.
diff --git a/src/mobilerun_sdk/types/device_create_response.py b/src/mobilerun_sdk/types/device_create_response.py
index c792c9f7..307565c2 100644
--- a/src/mobilerun_sdk/types/device_create_response.py
+++ b/src/mobilerun_sdk/types/device_create_response.py
@@ -2,6 +2,7 @@
from typing import Optional
from datetime import datetime
+from typing_extensions import Literal
from pydantic import Field as FieldInfo
@@ -21,6 +22,9 @@ class DeviceCreateResponse(BaseModel):
name: str
+ platform: Literal["android", "ios"]
+ """Operating system the device runs."""
+
state: str
state_message: str = FieldInfo(alias="stateMessage")
diff --git a/src/mobilerun_sdk/types/device_list_response.py b/src/mobilerun_sdk/types/device_list_response.py
index f8c1a26a..e4c0e942 100644
--- a/src/mobilerun_sdk/types/device_list_response.py
+++ b/src/mobilerun_sdk/types/device_list_response.py
@@ -2,6 +2,7 @@
from typing import List, Optional
from datetime import datetime
+from typing_extensions import Literal
from pydantic import Field as FieldInfo
@@ -22,6 +23,9 @@ class Item(BaseModel):
name: str
+ platform: Literal["android", "ios"]
+ """Operating system the device runs."""
+
state: str
state_message: str = FieldInfo(alias="stateMessage")
diff --git a/src/mobilerun_sdk/types/device_retrieve_capabilities_response.py b/src/mobilerun_sdk/types/device_retrieve_capabilities_response.py
index 2e02c5ea..f5a6020c 100644
--- a/src/mobilerun_sdk/types/device_retrieve_capabilities_response.py
+++ b/src/mobilerun_sdk/types/device_retrieve_capabilities_response.py
@@ -42,6 +42,8 @@ class Capabilities(BaseModel):
proxy: bool
+ recording: bool
+
reset: bool
shell: bool
@@ -54,6 +56,8 @@ class Capabilities(BaseModel):
time: bool
+ traffic_inspection: bool = FieldInfo(alias="trafficInspection")
+
class DeviceRetrieveCapabilitiesResponse(BaseModel):
capabilities: Capabilities
diff --git a/src/mobilerun_sdk/types/device_retrieve_response.py b/src/mobilerun_sdk/types/device_retrieve_response.py
index 6735522c..be523d09 100644
--- a/src/mobilerun_sdk/types/device_retrieve_response.py
+++ b/src/mobilerun_sdk/types/device_retrieve_response.py
@@ -2,6 +2,7 @@
from typing import Optional
from datetime import datetime
+from typing_extensions import Literal
from pydantic import Field as FieldInfo
@@ -21,6 +22,9 @@ class DeviceRetrieveResponse(BaseModel):
name: str
+ platform: Literal["android", "ios"]
+ """Operating system the device runs."""
+
state: str
state_message: str = FieldInfo(alias="stateMessage")
diff --git a/src/mobilerun_sdk/types/device_set_name_response.py b/src/mobilerun_sdk/types/device_set_name_response.py
index f7976eea..026ac9b1 100644
--- a/src/mobilerun_sdk/types/device_set_name_response.py
+++ b/src/mobilerun_sdk/types/device_set_name_response.py
@@ -2,6 +2,7 @@
from typing import Optional
from datetime import datetime
+from typing_extensions import Literal
from pydantic import Field as FieldInfo
@@ -21,6 +22,9 @@ class DeviceSetNameResponse(BaseModel):
name: str
+ platform: Literal["android", "ios"]
+ """Operating system the device runs."""
+
state: str
state_message: str = FieldInfo(alias="stateMessage")
diff --git a/src/mobilerun_sdk/types/device_wait_ready_response.py b/src/mobilerun_sdk/types/device_wait_ready_response.py
index 73a50c61..d8de894d 100644
--- a/src/mobilerun_sdk/types/device_wait_ready_response.py
+++ b/src/mobilerun_sdk/types/device_wait_ready_response.py
@@ -2,6 +2,7 @@
from typing import Optional
from datetime import datetime
+from typing_extensions import Literal
from pydantic import Field as FieldInfo
@@ -21,6 +22,9 @@ class DeviceWaitReadyResponse(BaseModel):
name: str
+ platform: Literal["android", "ios"]
+ """Operating system the device runs."""
+
state: str
state_message: str = FieldInfo(alias="stateMessage")
diff --git a/src/mobilerun_sdk/types/devices/__init__.py b/src/mobilerun_sdk/types/devices/__init__.py
index 6b5d3494..2e93fc88 100644
--- a/src/mobilerun_sdk/types/devices/__init__.py
+++ b/src/mobilerun_sdk/types/devices/__init__.py
@@ -54,12 +54,18 @@
from .state_screenshot_response import StateScreenshotResponse as StateScreenshotResponse
from .app_list_installs_response import AppListInstallsResponse as AppListInstallsResponse
from .media_session_create_params import MediaSessionCreateParams as MediaSessionCreateParams
+from .traffic_session_list_params import TrafficSessionListParams as TrafficSessionListParams
from .browser_execute_script_params import BrowserExecuteScriptParams as BrowserExecuteScriptParams
from .media_session_create_response import MediaSessionCreateResponse as MediaSessionCreateResponse
+from .traffic_session_create_params import TrafficSessionCreateParams as TrafficSessionCreateParams
+from .traffic_session_list_response import TrafficSessionListResponse as TrafficSessionListResponse
from .action_overlay_visible_response import ActionOverlayVisibleResponse as ActionOverlayVisibleResponse
from .browser_execute_script_response import BrowserExecuteScriptResponse as BrowserExecuteScriptResponse
from .media_session_activate_response import MediaSessionActivateResponse as MediaSessionActivateResponse
+from .traffic_session_create_response import TrafficSessionCreateResponse as TrafficSessionCreateResponse
+from .traffic_session_delete_response import TrafficSessionDeleteResponse as TrafficSessionDeleteResponse
from .action_set_overlay_visible_params import ActionSetOverlayVisibleParams as ActionSetOverlayVisibleParams
+from .traffic_session_retrieve_response import TrafficSessionRetrieveResponse as TrafficSessionRetrieveResponse
from .deep_link_execute_deep_link_params import DeepLinkExecuteDeepLinkParams as DeepLinkExecuteDeepLinkParams
from .media_session_retrieve_current_response import (
MediaSessionRetrieveCurrentResponse as MediaSessionRetrieveCurrentResponse,
diff --git a/src/mobilerun_sdk/types/devices/app_install_params.py b/src/mobilerun_sdk/types/devices/app_install_params.py
index f419dd4e..3624dc3a 100644
--- a/src/mobilerun_sdk/types/devices/app_install_params.py
+++ b/src/mobilerun_sdk/types/devices/app_install_params.py
@@ -21,9 +21,21 @@ class Variant0(TypedDict, total=False):
directly (200 on success, an error status on failure).
"""
+ country: str
+ """Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g.
+
+ MY or SG).
+ """
+
package_name: Annotated[str, PropertyInfo(alias="packageName")]
"""Android package name (e.g. com.example.app)"""
+ version_code: Annotated[int, PropertyInfo(alias="versionCode")]
+ """Optional exact app-library version code.
+
+ Use with country when multiple regional versions share an identifier.
+ """
+
x_device_display_id: Annotated[int, PropertyInfo(alias="X-Device-Display-ID")]
@@ -41,6 +53,18 @@ class Variant1(TypedDict, total=False):
bundle_id: Annotated[str, PropertyInfo(alias="bundleId")]
"""iOS bundle identifier (e.g. com.example.app)"""
+ country: str
+ """Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g.
+
+ MY or SG).
+ """
+
+ version_code: Annotated[int, PropertyInfo(alias="versionCode")]
+ """Optional exact app-library version code.
+
+ Use with country when multiple regional versions share an identifier.
+ """
+
x_device_display_id: Annotated[int, PropertyInfo(alias="X-Device-Display-ID")]
diff --git a/src/mobilerun_sdk/types/devices/app_list_installs_response.py b/src/mobilerun_sdk/types/devices/app_list_installs_response.py
index 796f7b2a..ae079f10 100644
--- a/src/mobilerun_sdk/types/devices/app_list_installs_response.py
+++ b/src/mobilerun_sdk/types/devices/app_list_installs_response.py
@@ -28,11 +28,10 @@ class Install(BaseModel):
updated_at: datetime = FieldInfo(alias="updatedAt")
- error_class: Optional[str] = FieldInfo(alias="errorClass", default=None)
- """Closed set: download_failed, adb_install_failed, panic, timeout, failed.
-
- Only present when status is failed.
- """
+ error_class: Optional[Literal["download_failed", "adb_install_failed", "panic", "timeout", "failed"]] = FieldInfo(
+ alias="errorClass", default=None
+ )
+ """Only present when status is failed."""
class AppListInstallsResponse(BaseModel):
diff --git a/src/mobilerun_sdk/types/devices/keyboard_write_params.py b/src/mobilerun_sdk/types/devices/keyboard_write_params.py
index c1340d7a..7bff865f 100644
--- a/src/mobilerun_sdk/types/devices/keyboard_write_params.py
+++ b/src/mobilerun_sdk/types/devices/keyboard_write_params.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing_extensions import Required, Annotated, TypedDict
+from typing_extensions import Literal, Required, Annotated, TypedDict
from ..._utils import PropertyInfo
@@ -14,6 +14,14 @@ class KeyboardWriteParams(TypedDict, total=False):
clear: bool
+ completion_mode: Annotated[Literal["accepted", "committed"], PropertyInfo(alias="completionMode")]
+ """Completion guarantee.
+
+ accepted returns after the input provider accepts the operation; committed
+ additionally waits for the focused UI state to contain the complete text or
+ become quiescent.
+ """
+
error_rate: Annotated[float, PropertyInfo(alias="errorRate")]
"""Per-character mistake rate for humantouch typing. -1 uses server default."""
diff --git a/src/mobilerun_sdk/types/devices/recording_start_params.py b/src/mobilerun_sdk/types/devices/recording_start_params.py
index 621a86aa..007181d3 100644
--- a/src/mobilerun_sdk/types/devices/recording_start_params.py
+++ b/src/mobilerun_sdk/types/devices/recording_start_params.py
@@ -14,6 +14,18 @@
class RecordingStartParams(TypedDict, total=False):
name: str
+ quality: int
+ """Capture quality from 1 (lowest) to 10 (full stream quality).
+
+ Defaults to the device's full quality. Honored by devices recording through the
+ portal stream bridge.
+ """
+
retention_days: Annotated[int, PropertyInfo(alias="retentionDays")]
types: Optional[SequenceNotStr[str]]
+ """
+ Artifacts to capture: trajectory (input actions), video, and audio (captured
+ into the video artifact, so it requires video; honored by portal stream-bridge
+ recorders). Defaults to trajectory and video.
+ """
diff --git a/src/mobilerun_sdk/types/devices/traffic_session_create_params.py b/src/mobilerun_sdk/types/devices/traffic_session_create_params.py
new file mode 100644
index 00000000..20d0df0a
--- /dev/null
+++ b/src/mobilerun_sdk/types/devices/traffic_session_create_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["TrafficSessionCreateParams"]
+
+
+class TrafficSessionCreateParams(TypedDict, total=False):
+ idempotency_key: Required[Annotated[str, PropertyInfo(alias="Idempotency-Key")]]
+
+ expires_in_seconds: Annotated[int, PropertyInfo(alias="expiresInSeconds")]
+
+ max_body_bytes: Annotated[int, PropertyInfo(alias="maxBodyBytes")]
diff --git a/src/mobilerun_sdk/types/devices/traffic_session_create_response.py b/src/mobilerun_sdk/types/devices/traffic_session_create_response.py
new file mode 100644
index 00000000..833e638b
--- /dev/null
+++ b/src/mobilerun_sdk/types/devices/traffic_session_create_response.py
@@ -0,0 +1,52 @@
+# 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__ = ["TrafficSessionCreateResponse", "Error", "Stream"]
+
+
+class Error(BaseModel):
+ code: str
+
+ message: str
+
+
+class Stream(BaseModel):
+ token: str
+
+ protocol: str
+
+ url: str
+
+
+class TrafficSessionCreateResponse(BaseModel):
+ id: str
+
+ created_at: datetime = FieldInfo(alias="createdAt")
+
+ device_id: str = FieldInfo(alias="deviceId")
+
+ expires_at: datetime = FieldInfo(alias="expiresAt")
+
+ max_body_bytes: int = FieldInfo(alias="maxBodyBytes")
+
+ retention: Literal["none"]
+
+ state: Literal["starting", "active", "stopping", "stopped", "failed", "expired"]
+
+ schema_: Optional[str] = FieldInfo(alias="$schema", default=None)
+ """A URL to the JSON Schema for this object."""
+
+ error: Optional[Error] = None
+
+ started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None)
+
+ stopped_at: Optional[datetime] = FieldInfo(alias="stoppedAt", default=None)
+
+ stream: Optional[Stream] = None
diff --git a/src/mobilerun_sdk/types/devices/traffic_session_delete_response.py b/src/mobilerun_sdk/types/devices/traffic_session_delete_response.py
new file mode 100644
index 00000000..4b1ff552
--- /dev/null
+++ b/src/mobilerun_sdk/types/devices/traffic_session_delete_response.py
@@ -0,0 +1,52 @@
+# 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__ = ["TrafficSessionDeleteResponse", "Error", "Stream"]
+
+
+class Error(BaseModel):
+ code: str
+
+ message: str
+
+
+class Stream(BaseModel):
+ token: str
+
+ protocol: str
+
+ url: str
+
+
+class TrafficSessionDeleteResponse(BaseModel):
+ id: str
+
+ created_at: datetime = FieldInfo(alias="createdAt")
+
+ device_id: str = FieldInfo(alias="deviceId")
+
+ expires_at: datetime = FieldInfo(alias="expiresAt")
+
+ max_body_bytes: int = FieldInfo(alias="maxBodyBytes")
+
+ retention: Literal["none"]
+
+ state: Literal["starting", "active", "stopping", "stopped", "failed", "expired"]
+
+ schema_: Optional[str] = FieldInfo(alias="$schema", default=None)
+ """A URL to the JSON Schema for this object."""
+
+ error: Optional[Error] = None
+
+ started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None)
+
+ stopped_at: Optional[datetime] = FieldInfo(alias="stoppedAt", default=None)
+
+ stream: Optional[Stream] = None
diff --git a/src/mobilerun_sdk/types/esim_selector_params.py b/src/mobilerun_sdk/types/devices/traffic_session_list_params.py
similarity index 66%
rename from src/mobilerun_sdk/types/esim_selector_params.py
rename to src/mobilerun_sdk/types/devices/traffic_session_list_params.py
index d5cd46c1..9685e594 100644
--- a/src/mobilerun_sdk/types/esim_selector_params.py
+++ b/src/mobilerun_sdk/types/devices/traffic_session_list_params.py
@@ -4,12 +4,12 @@
from typing_extensions import Annotated, TypedDict
-from .._utils import PropertyInfo
+from ..._utils import PropertyInfo
-__all__ = ["EsimSelectorParams"]
+__all__ = ["TrafficSessionListParams"]
-class EsimSelectorParams(TypedDict, total=False):
+class TrafficSessionListParams(TypedDict, total=False):
page: int
page_size: Annotated[int, PropertyInfo(alias="pageSize")]
diff --git a/src/mobilerun_sdk/types/devices/traffic_session_list_response.py b/src/mobilerun_sdk/types/devices/traffic_session_list_response.py
new file mode 100644
index 00000000..d4a13f54
--- /dev/null
+++ b/src/mobilerun_sdk/types/devices/traffic_session_list_response.py
@@ -0,0 +1,62 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+from ..shared.meta import Meta
+
+__all__ = ["TrafficSessionListResponse", "Item", "ItemError", "ItemStream"]
+
+
+class ItemError(BaseModel):
+ code: str
+
+ message: str
+
+
+class ItemStream(BaseModel):
+ token: str
+
+ protocol: str
+
+ url: str
+
+
+class Item(BaseModel):
+ id: str
+
+ created_at: datetime = FieldInfo(alias="createdAt")
+
+ device_id: str = FieldInfo(alias="deviceId")
+
+ expires_at: datetime = FieldInfo(alias="expiresAt")
+
+ max_body_bytes: int = FieldInfo(alias="maxBodyBytes")
+
+ retention: Literal["none"]
+
+ state: Literal["starting", "active", "stopping", "stopped", "failed", "expired"]
+
+ schema_: Optional[str] = FieldInfo(alias="$schema", default=None)
+ """A URL to the JSON Schema for this object."""
+
+ error: Optional[ItemError] = None
+
+ started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None)
+
+ stopped_at: Optional[datetime] = FieldInfo(alias="stoppedAt", default=None)
+
+ stream: Optional[ItemStream] = None
+
+
+class TrafficSessionListResponse(BaseModel):
+ items: Optional[List[Item]] = None
+
+ pagination: Meta
+
+ schema_: Optional[str] = FieldInfo(alias="$schema", default=None)
+ """A URL to the JSON Schema for this object."""
diff --git a/src/mobilerun_sdk/types/devices/traffic_session_retrieve_response.py b/src/mobilerun_sdk/types/devices/traffic_session_retrieve_response.py
new file mode 100644
index 00000000..6534ad06
--- /dev/null
+++ b/src/mobilerun_sdk/types/devices/traffic_session_retrieve_response.py
@@ -0,0 +1,52 @@
+# 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__ = ["TrafficSessionRetrieveResponse", "Error", "Stream"]
+
+
+class Error(BaseModel):
+ code: str
+
+ message: str
+
+
+class Stream(BaseModel):
+ token: str
+
+ protocol: str
+
+ url: str
+
+
+class TrafficSessionRetrieveResponse(BaseModel):
+ id: str
+
+ created_at: datetime = FieldInfo(alias="createdAt")
+
+ device_id: str = FieldInfo(alias="deviceId")
+
+ expires_at: datetime = FieldInfo(alias="expiresAt")
+
+ max_body_bytes: int = FieldInfo(alias="maxBodyBytes")
+
+ retention: Literal["none"]
+
+ state: Literal["starting", "active", "stopping", "stopped", "failed", "expired"]
+
+ schema_: Optional[str] = FieldInfo(alias="$schema", default=None)
+ """A URL to the JSON Schema for this object."""
+
+ error: Optional[Error] = None
+
+ started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None)
+
+ stopped_at: Optional[datetime] = FieldInfo(alias="stoppedAt", default=None)
+
+ stream: Optional[Stream] = None
diff --git a/src/mobilerun_sdk/types/esim_capacity_response.py b/src/mobilerun_sdk/types/esim_capacity_response.py
deleted file mode 100644
index 69204004..00000000
--- a/src/mobilerun_sdk/types/esim_capacity_response.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from pydantic import Field as FieldInfo
-
-from .._models import BaseModel
-
-__all__ = ["EsimCapacityResponse", "Data"]
-
-
-class Data(BaseModel):
- available: bool
-
- free_devices: int = FieldInfo(alias="freeDevices")
-
-
-class EsimCapacityResponse(BaseModel):
- data: Data
diff --git a/src/mobilerun_sdk/types/esim_confirm_payment_response.py b/src/mobilerun_sdk/types/esim_confirm_payment_response.py
deleted file mode 100644
index d981ab88..00000000
--- a/src/mobilerun_sdk/types/esim_confirm_payment_response.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# 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__ = ["EsimConfirmPaymentResponse", "Data"]
-
-
-class Data(BaseModel):
- id: str
-
- carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None)
-
- country_code: Optional[str] = FieldInfo(alias="countryCode", default=None)
-
- created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None)
-
- created_by: Optional[str] = FieldInfo(alias="createdBy", default=None)
-
- device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
-
- device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None)
-
- iccid: Optional[str] = None
-
- msisdn: Optional[str] = None
-
- name: Optional[str] = None
-
- network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None)
-
- source: Literal["stocked", "byo"]
-
- status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"]
-
- subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None)
-
- updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
-
- cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None)
-
- checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None)
-
- current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
-
- exempt: Optional[bool] = None
-
- rent_status: Optional[
- Literal[
- "not_applicable",
- "exempt",
- "inactive",
- "awaiting_payment",
- "active",
- "cancel_pending",
- "refund_pending",
- "retiring",
- "billing_error",
- ]
- ] = FieldInfo(alias="rentStatus", default=None)
-
-
-class EsimConfirmPaymentResponse(BaseModel):
- data: Data
diff --git a/src/mobilerun_sdk/types/esim_create_params.py b/src/mobilerun_sdk/types/esim_create_params.py
deleted file mode 100644
index 973cbd1d..00000000
--- a/src/mobilerun_sdk/types/esim_create_params.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-from typing_extensions import Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["EsimCreateParams"]
-
-
-class EsimCreateParams(TypedDict, total=False):
- idempotency_key: Annotated[str, PropertyInfo(alias="idempotencyKey")]
- """
- Client-supplied key; replaying the same key returns the original purchase
- instead of buying again
- """
-
- name: Optional[str]
- """Optional user-defined display label — NFC-normalized, up to 15 GRAPHEMES.
-
- Omit or null for no label.
- """
diff --git a/src/mobilerun_sdk/types/esim_create_response.py b/src/mobilerun_sdk/types/esim_create_response.py
deleted file mode 100644
index 11111f7a..00000000
--- a/src/mobilerun_sdk/types/esim_create_response.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# 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__ = ["EsimCreateResponse", "Data"]
-
-
-class Data(BaseModel):
- id: str
-
- carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None)
-
- country_code: Optional[str] = FieldInfo(alias="countryCode", default=None)
-
- created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None)
-
- created_by: Optional[str] = FieldInfo(alias="createdBy", default=None)
-
- device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
-
- device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None)
-
- iccid: Optional[str] = None
-
- msisdn: Optional[str] = None
-
- name: Optional[str] = None
-
- network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None)
-
- source: Literal["stocked", "byo"]
-
- status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"]
-
- subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None)
-
- updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
-
- cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None)
-
- checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None)
-
- current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
-
- exempt: Optional[bool] = None
-
- rent_status: Optional[
- Literal[
- "not_applicable",
- "exempt",
- "inactive",
- "awaiting_payment",
- "active",
- "cancel_pending",
- "refund_pending",
- "retiring",
- "billing_error",
- ]
- ] = FieldInfo(alias="rentStatus", default=None)
-
-
-class EsimCreateResponse(BaseModel):
- data: Data
diff --git a/src/mobilerun_sdk/types/esim_import_params.py b/src/mobilerun_sdk/types/esim_import_params.py
deleted file mode 100644
index 59433916..00000000
--- a/src/mobilerun_sdk/types/esim_import_params.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-from typing_extensions import Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["EsimImportParams"]
-
-
-class EsimImportParams(TypedDict, total=False):
- auto_install: Annotated[bool, PropertyInfo(alias="autoInstall")]
- """Rent OFF only: dispatch install-on-device immediately after a successful import.
-
- No-op when ESIM_BYO_RENT_ENABLED=true.
- """
-
- carrier_name: Annotated[str, PropertyInfo(alias="carrierName")]
-
- confirmation_code: Annotated[str, PropertyInfo(alias="confirmationCode")]
-
- country_code: Annotated[str, PropertyInfo(alias="countryCode")]
-
- device_id: Annotated[str, PropertyInfo(alias="deviceId")]
- """physedge device id to auto-install onto; requires autoInstall:true and rent OFF.
-
- Omit for a random pool device.
- """
-
- idempotency_key: Annotated[str, PropertyInfo(alias="idempotencyKey")]
- """
- Client-supplied key; replaying the same key+request returns the original import
- instead of importing again
- """
-
- lpa_code: Annotated[str, PropertyInfo(alias="lpaCode")]
- """Full LPA activation code"""
-
- matching_id: Annotated[str, PropertyInfo(alias="matchingId")]
-
- msisdn: str
- """
- Self-reported E.164 MSISDN for this eSIM's line — an unverified label, never
- used for routing
- """
-
- name: Optional[str]
- """
- User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code
- units; an emoji/flag may span several). Omit/null/empty/whitespace-only leaves
- it unset.
- """
-
- notes: str
-
- smdp_address: Annotated[str, PropertyInfo(alias="smdpAddress")]
- """SM-DP+ activation host — bare hostname ONLY, no port/scheme/path."""
diff --git a/src/mobilerun_sdk/types/esim_import_response.py b/src/mobilerun_sdk/types/esim_import_response.py
deleted file mode 100644
index 5ab93dba..00000000
--- a/src/mobilerun_sdk/types/esim_import_response.py
+++ /dev/null
@@ -1,204 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Union, Optional
-from datetime import datetime
-from typing_extensions import Literal, TypeAlias
-
-from pydantic import Field as FieldInfo
-
-from .._models import BaseModel
-
-__all__ = [
- "EsimImportResponse",
- "Data",
- "DataPublicEsim",
- "DataEsimAwaitingPaymentResponse",
- "DataEsimAwaitingPaymentResponseEsim",
- "DataEsimImportInstallDispatchFailedResponse",
- "DataEsimImportInstallDispatchFailedResponseInstallDispatch",
-]
-
-
-class DataPublicEsim(BaseModel):
- id: str
-
- carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None)
-
- country_code: Optional[str] = FieldInfo(alias="countryCode", default=None)
-
- created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None)
-
- created_by: Optional[str] = FieldInfo(alias="createdBy", default=None)
-
- device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
-
- device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None)
-
- iccid: Optional[str] = None
-
- msisdn: Optional[str] = None
-
- name: Optional[str] = None
-
- network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None)
-
- source: Literal["stocked", "byo"]
-
- status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"]
-
- subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None)
-
- updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
-
- cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None)
-
- checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None)
-
- current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
-
- exempt: Optional[bool] = None
-
- rent_status: Optional[
- Literal[
- "not_applicable",
- "exempt",
- "inactive",
- "awaiting_payment",
- "active",
- "cancel_pending",
- "refund_pending",
- "retiring",
- "billing_error",
- ]
- ] = FieldInfo(alias="rentStatus", default=None)
-
-
-class DataEsimAwaitingPaymentResponseEsim(BaseModel):
- id: str
-
- carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None)
-
- country_code: Optional[str] = FieldInfo(alias="countryCode", default=None)
-
- created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None)
-
- created_by: Optional[str] = FieldInfo(alias="createdBy", default=None)
-
- device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
-
- device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None)
-
- iccid: Optional[str] = None
-
- msisdn: Optional[str] = None
-
- name: Optional[str] = None
-
- network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None)
-
- source: Literal["stocked", "byo"]
-
- status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"]
-
- subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None)
-
- updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
-
- cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None)
-
- checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None)
-
- current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
-
- exempt: Optional[bool] = None
-
- rent_status: Optional[
- Literal[
- "not_applicable",
- "exempt",
- "inactive",
- "awaiting_payment",
- "active",
- "cancel_pending",
- "refund_pending",
- "retiring",
- "billing_error",
- ]
- ] = FieldInfo(alias="rentStatus", default=None)
-
-
-class DataEsimAwaitingPaymentResponse(BaseModel):
- checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None)
-
- esim: DataEsimAwaitingPaymentResponseEsim
-
- rent_status: Literal["awaiting_payment"] = FieldInfo(alias="rentStatus")
-
-
-class DataEsimImportInstallDispatchFailedResponseInstallDispatch(BaseModel):
- ok: Literal[False]
-
- reason: str
-
-
-class DataEsimImportInstallDispatchFailedResponse(BaseModel):
- id: str
-
- carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None)
-
- country_code: Optional[str] = FieldInfo(alias="countryCode", default=None)
-
- created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None)
-
- created_by: Optional[str] = FieldInfo(alias="createdBy", default=None)
-
- device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
-
- device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None)
-
- iccid: Optional[str] = None
-
- install_dispatch: DataEsimImportInstallDispatchFailedResponseInstallDispatch = FieldInfo(alias="installDispatch")
-
- msisdn: Optional[str] = None
-
- name: Optional[str] = None
-
- network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None)
-
- source: Literal["stocked", "byo"]
-
- status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"]
-
- subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None)
-
- updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
-
- cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None)
-
- checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None)
-
- current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
-
- exempt: Optional[bool] = None
-
- rent_status: Optional[
- Literal[
- "not_applicable",
- "exempt",
- "inactive",
- "awaiting_payment",
- "active",
- "cancel_pending",
- "refund_pending",
- "retiring",
- "billing_error",
- ]
- ] = FieldInfo(alias="rentStatus", default=None)
-
-
-Data: TypeAlias = Union[DataPublicEsim, DataEsimAwaitingPaymentResponse, DataEsimImportInstallDispatchFailedResponse]
-
-
-class EsimImportResponse(BaseModel):
- data: Data
diff --git a/src/mobilerun_sdk/types/esim_install_params.py b/src/mobilerun_sdk/types/esim_install_params.py
deleted file mode 100644
index ca23a433..00000000
--- a/src/mobilerun_sdk/types/esim_install_params.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["EsimInstallParams"]
-
-
-class EsimInstallParams(TypedDict, total=False):
- device_id: Annotated[str, PropertyInfo(alias="deviceId")]
- """physedge device id to install the eSIM onto; omit for a random pool device"""
diff --git a/src/mobilerun_sdk/types/esim_install_response.py b/src/mobilerun_sdk/types/esim_install_response.py
deleted file mode 100644
index 24ea2f92..00000000
--- a/src/mobilerun_sdk/types/esim_install_response.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# 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__ = ["EsimInstallResponse", "Data"]
-
-
-class Data(BaseModel):
- id: str
-
- carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None)
-
- country_code: Optional[str] = FieldInfo(alias="countryCode", default=None)
-
- created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None)
-
- created_by: Optional[str] = FieldInfo(alias="createdBy", default=None)
-
- device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
-
- device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None)
-
- iccid: Optional[str] = None
-
- msisdn: Optional[str] = None
-
- name: Optional[str] = None
-
- network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None)
-
- source: Literal["stocked", "byo"]
-
- status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"]
-
- subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None)
-
- updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
-
- cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None)
-
- checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None)
-
- current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
-
- exempt: Optional[bool] = None
-
- rent_status: Optional[
- Literal[
- "not_applicable",
- "exempt",
- "inactive",
- "awaiting_payment",
- "active",
- "cancel_pending",
- "refund_pending",
- "retiring",
- "billing_error",
- ]
- ] = FieldInfo(alias="rentStatus", default=None)
-
-
-class EsimInstallResponse(BaseModel):
- data: Data
diff --git a/src/mobilerun_sdk/types/esim_install_status_response.py b/src/mobilerun_sdk/types/esim_install_status_response.py
deleted file mode 100644
index 87f8c3e5..00000000
--- a/src/mobilerun_sdk/types/esim_install_status_response.py
+++ /dev/null
@@ -1,93 +0,0 @@
-# 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__ = ["EsimInstallStatusResponse", "Data", "DataEsim"]
-
-
-class DataEsim(BaseModel):
- id: str
-
- carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None)
-
- country_code: Optional[str] = FieldInfo(alias="countryCode", default=None)
-
- created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None)
-
- created_by: Optional[str] = FieldInfo(alias="createdBy", default=None)
-
- device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
-
- device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None)
-
- iccid: Optional[str] = None
-
- msisdn: Optional[str] = None
-
- name: Optional[str] = None
-
- network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None)
-
- source: Literal["stocked", "byo"]
-
- status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"]
-
- subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None)
-
- updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
-
- cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None)
-
- checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None)
-
- current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
-
- exempt: Optional[bool] = None
-
- rent_status: Optional[
- Literal[
- "not_applicable",
- "exempt",
- "inactive",
- "awaiting_payment",
- "active",
- "cancel_pending",
- "refund_pending",
- "retiring",
- "billing_error",
- ]
- ] = FieldInfo(alias="rentStatus", default=None)
-
-
-class Data(BaseModel):
- esim: DataEsim
-
- operation_id: Optional[str] = FieldInfo(alias="operationId", default=None)
-
- status: Optional[
- Literal[
- "installing",
- "pending_download",
- "downloading",
- "downloaded",
- "enabling",
- "configuring_apn",
- "active",
- "download_failed",
- "enable_failed",
- "download_outcome_unknown",
- "install_failed",
- "physical_removal_unconfirmed",
- "deleted",
- ]
- ] = None
-
-
-class EsimInstallStatusResponse(BaseModel):
- data: Data
diff --git a/src/mobilerun_sdk/types/esim_list_params.py b/src/mobilerun_sdk/types/esim_list_params.py
deleted file mode 100644
index a653308b..00000000
--- a/src/mobilerun_sdk/types/esim_list_params.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["EsimListParams"]
-
-
-class EsimListParams(TypedDict, total=False):
- mine: Literal["true", "false"]
- """Only include eSIMs created by the calling actor."""
-
- page: int
-
- page_size: Annotated[int, PropertyInfo(alias="pageSize")]
-
- status: Literal["all", "in_stock", "owned", "installing", "installed", "install_failed", "retired"]
diff --git a/src/mobilerun_sdk/types/esim_list_response.py b/src/mobilerun_sdk/types/esim_list_response.py
deleted file mode 100644
index 5c236e21..00000000
--- a/src/mobilerun_sdk/types/esim_list_response.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-from datetime import datetime
-from typing_extensions import Literal
-
-from pydantic import Field as FieldInfo
-
-from .._models import BaseModel
-from .shared.pagination import Pagination
-
-__all__ = ["EsimListResponse", "Item"]
-
-
-class Item(BaseModel):
- id: str
-
- carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None)
-
- country_code: Optional[str] = FieldInfo(alias="countryCode", default=None)
-
- created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None)
-
- created_by: Optional[str] = FieldInfo(alias="createdBy", default=None)
-
- device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
-
- device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None)
-
- iccid: Optional[str] = None
-
- msisdn: Optional[str] = None
-
- name: Optional[str] = None
-
- network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None)
-
- source: Literal["stocked", "byo"]
-
- status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"]
-
- subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None)
-
- updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
-
- cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None)
-
- checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None)
-
- current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
-
- exempt: Optional[bool] = None
-
- rent_status: Optional[
- Literal[
- "not_applicable",
- "exempt",
- "inactive",
- "awaiting_payment",
- "active",
- "cancel_pending",
- "refund_pending",
- "retiring",
- "billing_error",
- ]
- ] = FieldInfo(alias="rentStatus", default=None)
-
-
-class EsimListResponse(BaseModel):
- items: List[Item]
-
- pagination: Pagination
diff --git a/src/mobilerun_sdk/types/esim_retrieve_response.py b/src/mobilerun_sdk/types/esim_retrieve_response.py
deleted file mode 100644
index 41cf5a88..00000000
--- a/src/mobilerun_sdk/types/esim_retrieve_response.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# 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__ = ["EsimRetrieveResponse", "Data"]
-
-
-class Data(BaseModel):
- id: str
-
- carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None)
-
- country_code: Optional[str] = FieldInfo(alias="countryCode", default=None)
-
- created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None)
-
- created_by: Optional[str] = FieldInfo(alias="createdBy", default=None)
-
- device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
-
- device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None)
-
- iccid: Optional[str] = None
-
- msisdn: Optional[str] = None
-
- name: Optional[str] = None
-
- network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None)
-
- source: Literal["stocked", "byo"]
-
- status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"]
-
- subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None)
-
- updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
-
- cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None)
-
- checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None)
-
- current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
-
- exempt: Optional[bool] = None
-
- rent_status: Optional[
- Literal[
- "not_applicable",
- "exempt",
- "inactive",
- "awaiting_payment",
- "active",
- "cancel_pending",
- "refund_pending",
- "retiring",
- "billing_error",
- ]
- ] = FieldInfo(alias="rentStatus", default=None)
-
-
-class EsimRetrieveResponse(BaseModel):
- data: Data
diff --git a/src/mobilerun_sdk/types/esim_selector_response.py b/src/mobilerun_sdk/types/esim_selector_response.py
deleted file mode 100644
index 4288bcf9..00000000
--- a/src/mobilerun_sdk/types/esim_selector_response.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-from typing_extensions import Literal
-
-from pydantic import Field as FieldInfo
-
-from .._models import BaseModel
-from .shared.pagination import Pagination
-
-__all__ = ["EsimSelectorResponse", "Item"]
-
-
-class Item(BaseModel):
- id: str
-
- carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None)
-
- iccid: Optional[str] = None
-
- msisdn: Optional[str] = None
-
- name: Optional[str] = None
-
- source: Literal["stocked", "byo"]
-
- status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"]
-
-
-class EsimSelectorResponse(BaseModel):
- items: List[Item]
-
- pagination: Pagination
diff --git a/src/mobilerun_sdk/types/esim_update_params.py b/src/mobilerun_sdk/types/esim_update_params.py
deleted file mode 100644
index a0fdc6de..00000000
--- a/src/mobilerun_sdk/types/esim_update_params.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-from typing_extensions import TypedDict
-
-__all__ = ["EsimUpdateParams"]
-
-
-class EsimUpdateParams(TypedDict, total=False):
- msisdn: Optional[str]
- """Self-reported E.164 MSISDN for this eSIM's line.
-
- Omit to leave unchanged; null/empty clears it. An unverified label — never used
- for routing.
- """
-
- name: Optional[str]
- """
- User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code
- units; an emoji/flag may span several). Omit to leave unchanged;
- null/empty/whitespace-only clears it.
- """
diff --git a/src/mobilerun_sdk/types/esim_update_response.py b/src/mobilerun_sdk/types/esim_update_response.py
deleted file mode 100644
index 407eb7d9..00000000
--- a/src/mobilerun_sdk/types/esim_update_response.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# 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__ = ["EsimUpdateResponse", "Data"]
-
-
-class Data(BaseModel):
- id: str
-
- carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None)
-
- country_code: Optional[str] = FieldInfo(alias="countryCode", default=None)
-
- created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None)
-
- created_by: Optional[str] = FieldInfo(alias="createdBy", default=None)
-
- device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
-
- device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None)
-
- iccid: Optional[str] = None
-
- msisdn: Optional[str] = None
-
- name: Optional[str] = None
-
- network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None)
-
- source: Literal["stocked", "byo"]
-
- status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"]
-
- subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None)
-
- updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
-
- cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None)
-
- checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None)
-
- current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
-
- exempt: Optional[bool] = None
-
- rent_status: Optional[
- Literal[
- "not_applicable",
- "exempt",
- "inactive",
- "awaiting_payment",
- "active",
- "cancel_pending",
- "refund_pending",
- "retiring",
- "billing_error",
- ]
- ] = FieldInfo(alias="rentStatus", default=None)
-
-
-class EsimUpdateResponse(BaseModel):
- data: Data
diff --git a/src/mobilerun_sdk/types/esims/__init__.py b/src/mobilerun_sdk/types/esims/__init__.py
deleted file mode 100644
index d059c99c..00000000
--- a/src/mobilerun_sdk/types/esims/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from .message_list_params import MessageListParams as MessageListParams
-from .message_send_params import MessageSendParams as MessageSendParams
-from .message_list_response import MessageListResponse as MessageListResponse
-from .message_send_response import MessageSendResponse as MessageSendResponse
diff --git a/src/mobilerun_sdk/types/esims/message_list_params.py b/src/mobilerun_sdk/types/esims/message_list_params.py
deleted file mode 100644
index c55e68af..00000000
--- a/src/mobilerun_sdk/types/esims/message_list_params.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Annotated, TypedDict
-
-from ..._utils import PropertyInfo
-
-__all__ = ["MessageListParams"]
-
-
-class MessageListParams(TypedDict, total=False):
- direction: Literal["all", "inbound", "outbound"]
-
- number_id: Annotated[str, PropertyInfo(alias="numberId")]
-
- page: int
-
- page_size: Annotated[int, PropertyInfo(alias="pageSize")]
-
- peer_key: Annotated[str, PropertyInfo(alias="peerKey")]
-
- peer_number: Annotated[str, PropertyInfo(alias="peerNumber")]
-
- status: Literal[
- "all", "received", "queued", "claimed", "sending", "sent", "sent_unconfirmed", "delivered", "failed"
- ]
diff --git a/src/mobilerun_sdk/types/esims/message_list_response.py b/src/mobilerun_sdk/types/esims/message_list_response.py
deleted file mode 100644
index c04b3d46..00000000
--- a/src/mobilerun_sdk/types/esims/message_list_response.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-from datetime import datetime
-from typing_extensions import Literal
-
-from pydantic import Field as FieldInfo
-
-from ..._models import BaseModel
-from ..shared.pagination import Pagination
-
-__all__ = ["MessageListResponse", "Item"]
-
-
-class Item(BaseModel):
- id: str
-
- body: Optional[str] = None
-
- created_at: datetime = FieldInfo(alias="createdAt")
-
- delivery_status: Optional[str] = FieldInfo(alias="deliveryStatus", default=None)
-
- detected_sender: Optional[str] = FieldInfo(alias="detectedSender", default=None)
-
- direction: Literal["inbound", "outbound"]
-
- esim_id: Optional[str] = FieldInfo(alias="esimId", default=None)
-
- occurred_at: datetime = FieldInfo(alias="occurredAt")
-
- peer_key: Optional[str] = FieldInfo(alias="peerKey", default=None)
-
- peer_number: Optional[str] = FieldInfo(alias="peerNumber", default=None)
-
- provider_code: Optional[str] = FieldInfo(alias="providerCode", default=None)
-
- status: Literal["received", "queued", "claimed", "sending", "sent", "sent_unconfirmed", "delivered", "failed"]
-
-
-class MessageListResponse(BaseModel):
- items: List[Item]
-
- pagination: Pagination
diff --git a/src/mobilerun_sdk/types/esims/message_send_params.py b/src/mobilerun_sdk/types/esims/message_send_params.py
deleted file mode 100644
index 48c2c65a..00000000
--- a/src/mobilerun_sdk/types/esims/message_send_params.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, Annotated, TypedDict
-
-from ..._utils import PropertyInfo
-
-__all__ = ["MessageSendParams"]
-
-
-class MessageSendParams(TypedDict, total=False):
- body: Required[str]
- """
- SMS body text (max 320 chars — smaller than the admin tier's cap; see the
- schema's own doc comment for why)
- """
-
- to: Required[str]
- """
- Recipient phone number — normalized to E.164 (spaces/dashes/dots stripped);
- rejected with 400 if it doesn't validate as E.164 afterward.
- """
-
- client_request_id: Annotated[str, PropertyInfo(alias="clientRequestId")]
- """Client-supplied idempotency key, scoped to (owner, esimId, key).
-
- Replaying the same key + identical payload returns the original send; the same
- key with a DIFFERENT payload is a 409 conflict.
- """
-
- delivery_report: Annotated[bool, PropertyInfo(alias="deliveryReport")]
- """
- Wait for physedge to confirm carrier delivery before completing the send (adds
- executor-side latency, never on this request — sends are always async/202).
- Defaults to false for the public tier (opt-in, unlike the admin tier's
- default-true).
- """
diff --git a/src/mobilerun_sdk/types/esims/message_send_response.py b/src/mobilerun_sdk/types/esims/message_send_response.py
deleted file mode 100644
index 86e545d6..00000000
--- a/src/mobilerun_sdk/types/esims/message_send_response.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# 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__ = ["MessageSendResponse", "Data"]
-
-
-class Data(BaseModel):
- id: str
-
- body: Optional[str] = None
-
- created_at: datetime = FieldInfo(alias="createdAt")
-
- delivery_status: Optional[str] = FieldInfo(alias="deliveryStatus", default=None)
-
- detected_sender: Optional[str] = FieldInfo(alias="detectedSender", default=None)
-
- direction: Literal["inbound", "outbound"]
-
- esim_id: Optional[str] = FieldInfo(alias="esimId", default=None)
-
- occurred_at: datetime = FieldInfo(alias="occurredAt")
-
- peer_key: Optional[str] = FieldInfo(alias="peerKey", default=None)
-
- peer_number: Optional[str] = FieldInfo(alias="peerNumber", default=None)
-
- provider_code: Optional[str] = FieldInfo(alias="providerCode", default=None)
-
- status: Literal["received", "queued", "claimed", "sending", "sent", "sent_unconfirmed", "delivered", "failed"]
-
-
-class MessageSendResponse(BaseModel):
- data: Data
diff --git a/src/mobilerun_sdk/types/file_confirm_response.py b/src/mobilerun_sdk/types/file_confirm_response.py
deleted file mode 100644
index 7ee2a30c..00000000
--- a/src/mobilerun_sdk/types/file_confirm_response.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# 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__ = ["FileConfirmResponse"]
-
-
-class FileConfirmResponse(BaseModel):
- actual_size_bytes: float = FieldInfo(alias="actualSizeBytes")
-
- created_at: datetime = FieldInfo(alias="createdAt")
-
- created_by: Literal["user", "agent", "workflow"] = FieldInfo(alias="createdBy")
-
- display_name: Optional[str] = FieldInfo(alias="displayName", default=None)
-
- enabled: bool
-
- file_id: str = FieldInfo(alias="fileId")
-
- filename: str
-
- mime_type: str = FieldInfo(alias="mimeType")
-
- size_bytes: float = FieldInfo(alias="sizeBytes")
-
- state: Literal["ready"]
-
- zone: Literal["user", "agent", "workflow", "skills"]
diff --git a/src/mobilerun_sdk/types/file_list_params.py b/src/mobilerun_sdk/types/file_list_params.py
deleted file mode 100644
index fe1d5561..00000000
--- a/src/mobilerun_sdk/types/file_list_params.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, TypedDict
-
-__all__ = ["FileListParams"]
-
-
-class FileListParams(TypedDict, total=False):
- zone: Literal["user", "agent", "workflow", "skills"]
diff --git a/src/mobilerun_sdk/types/file_list_response.py b/src/mobilerun_sdk/types/file_list_response.py
deleted file mode 100644
index 014c11fb..00000000
--- a/src/mobilerun_sdk/types/file_list_response.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-from datetime import datetime
-from typing_extensions import Literal
-
-from pydantic import Field as FieldInfo
-
-from .._models import BaseModel
-
-__all__ = ["FileListResponse", "File", "Quota"]
-
-
-class File(BaseModel):
- created_at: datetime = FieldInfo(alias="createdAt")
-
- created_by: Literal["user", "agent", "workflow"] = FieldInfo(alias="createdBy")
-
- display_name: Optional[str] = FieldInfo(alias="displayName", default=None)
-
- enabled: bool
-
- file_id: str = FieldInfo(alias="fileId")
-
- filename: str
-
- mime_type: str = FieldInfo(alias="mimeType")
-
- size_bytes: float = FieldInfo(alias="sizeBytes")
-
- zone: Literal["user", "agent", "workflow", "skills"]
-
-
-class Quota(BaseModel):
- current_bytes: int = FieldInfo(alias="currentBytes")
-
- quota_bytes: int = FieldInfo(alias="quotaBytes")
-
-
-class FileListResponse(BaseModel):
- files: List[File]
-
- quota: Quota
diff --git a/src/mobilerun_sdk/types/file_update_params.py b/src/mobilerun_sdk/types/file_update_params.py
deleted file mode 100644
index e6da4e5a..00000000
--- a/src/mobilerun_sdk/types/file_update_params.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-from typing_extensions import Annotated, TypedDict
-
-from .._utils import PropertyInfo
-
-__all__ = ["FileUpdateParams"]
-
-
-class FileUpdateParams(TypedDict, total=False):
- display_name: Annotated[Optional[str], PropertyInfo(alias="displayName")]
-
- enabled: bool
diff --git a/src/mobilerun_sdk/types/file_update_response.py b/src/mobilerun_sdk/types/file_update_response.py
deleted file mode 100644
index a3903256..00000000
--- a/src/mobilerun_sdk/types/file_update_response.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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__ = ["FileUpdateResponse"]
-
-
-class FileUpdateResponse(BaseModel):
- created_at: datetime = FieldInfo(alias="createdAt")
-
- created_by: Literal["user", "agent", "workflow"] = FieldInfo(alias="createdBy")
-
- display_name: Optional[str] = FieldInfo(alias="displayName", default=None)
-
- enabled: bool
-
- file_id: str = FieldInfo(alias="fileId")
-
- filename: str
-
- mime_type: str = FieldInfo(alias="mimeType")
-
- size_bytes: float = FieldInfo(alias="sizeBytes")
-
- zone: Literal["user", "agent", "workflow", "skills"]
diff --git a/src/mobilerun_sdk/types/mailbox_create_params.py b/src/mobilerun_sdk/types/mailbox_create_params.py
index bd5b7ce5..68cf68f8 100644
--- a/src/mobilerun_sdk/types/mailbox_create_params.py
+++ b/src/mobilerun_sdk/types/mailbox_create_params.py
@@ -12,18 +12,20 @@
class MailboxCreateParams(TypedDict, total=False):
client_request_id: Required[Annotated[str, PropertyInfo(alias="clientRequestId")]]
- billing_preference: Annotated[Literal["included", "rent"], PropertyInfo(alias="billingPreference")]
- """Funding preference.
+ billing_preference: Annotated[Literal["included", "included_only", "rent"], PropertyInfo(alias="billingPreference")]
+ """
+ included uses package capacity when available and otherwise starts paid
+ checkout; included_only fails without creating a paid reservation when no
+ included slot remains; rent always starts paid checkout.
+ """
+
+ domain_id: Annotated[str, PropertyInfo(alias="domainId")]
+ """Optional active custom mailbox domain owned by the caller.
- Omit or use included for included-first activation; rent always preserves
- package capacity and starts paid checkout.
+ Omit to use the system domain.
"""
label: str
local_part: Annotated[str, PropertyInfo(alias="localPart")]
- """Optional full mailbox local part (the address before "@").
-
- Trimmed and lowercased before validation. Omit for a random, non-guessable
- mx\\__-prefixed address.
- """
+ """Optional mailbox name before the "@". Omit to generate a random address."""
diff --git a/src/mobilerun_sdk/types/mailbox_create_response.py b/src/mobilerun_sdk/types/mailbox_create_response.py
index 0ed4e6c4..2bb8b3c9 100644
--- a/src/mobilerun_sdk/types/mailbox_create_response.py
+++ b/src/mobilerun_sdk/types/mailbox_create_response.py
@@ -26,7 +26,7 @@ class Data(BaseModel):
address: Optional[str] = None
- billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode")
+ billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode")
cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd")
@@ -38,6 +38,8 @@ class Data(BaseModel):
current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
+ domain_id: Optional[str] = FieldInfo(alias="domainId", default=None)
+
inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages")
label: Optional[str] = None
diff --git a/src/mobilerun_sdk/types/mailbox_delete_response.py b/src/mobilerun_sdk/types/mailbox_delete_response.py
index 7b6675cd..ac6cd9b8 100644
--- a/src/mobilerun_sdk/types/mailbox_delete_response.py
+++ b/src/mobilerun_sdk/types/mailbox_delete_response.py
@@ -26,7 +26,7 @@ class Data(BaseModel):
address: Optional[str] = None
- billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode")
+ billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode")
cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd")
@@ -38,6 +38,8 @@ class Data(BaseModel):
current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
+ domain_id: Optional[str] = FieldInfo(alias="domainId", default=None)
+
inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages")
label: Optional[str] = None
diff --git a/src/mobilerun_sdk/types/mailbox_list_response.py b/src/mobilerun_sdk/types/mailbox_list_response.py
index df935fc8..70ace920 100644
--- a/src/mobilerun_sdk/types/mailbox_list_response.py
+++ b/src/mobilerun_sdk/types/mailbox_list_response.py
@@ -27,7 +27,7 @@ class Item(BaseModel):
address: Optional[str] = None
- billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode")
+ billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode")
cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd")
@@ -39,6 +39,8 @@ class Item(BaseModel):
current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
+ domain_id: Optional[str] = FieldInfo(alias="domainId", default=None)
+
inbound_messages: ItemInboundMessages = FieldInfo(alias="inboundMessages")
label: Optional[str] = None
diff --git a/src/mobilerun_sdk/types/mailbox_otp_response.py b/src/mobilerun_sdk/types/mailbox_otp_response.py
index 28ce8f48..540069ac 100644
--- a/src/mobilerun_sdk/types/mailbox_otp_response.py
+++ b/src/mobilerun_sdk/types/mailbox_otp_response.py
@@ -13,7 +13,7 @@
class Data(BaseModel):
code: str
- """String to preserve leading zeros"""
+ """OTP code as text to preserve leading zeros."""
confidence: Literal["high", "medium", "low"]
diff --git a/src/mobilerun_sdk/types/mailbox_restart_params.py b/src/mobilerun_sdk/types/mailbox_restart_params.py
index 497bb7e0..ca174720 100644
--- a/src/mobilerun_sdk/types/mailbox_restart_params.py
+++ b/src/mobilerun_sdk/types/mailbox_restart_params.py
@@ -10,9 +10,9 @@
class MailboxRestartParams(TypedDict, total=False):
- billing_preference: Annotated[Literal["included", "rent"], PropertyInfo(alias="billingPreference")]
- """Funding preference.
-
- Omit or use included for included-first activation; rent always preserves
- package capacity and starts paid checkout.
+ billing_preference: Annotated[Literal["included", "included_only", "rent"], PropertyInfo(alias="billingPreference")]
+ """
+ included uses package capacity when available and otherwise starts paid
+ checkout; included_only fails without creating a paid reservation when no
+ included slot remains; rent always starts paid checkout.
"""
diff --git a/src/mobilerun_sdk/types/mailbox_restart_response.py b/src/mobilerun_sdk/types/mailbox_restart_response.py
index 4bef7939..ab9e1d79 100644
--- a/src/mobilerun_sdk/types/mailbox_restart_response.py
+++ b/src/mobilerun_sdk/types/mailbox_restart_response.py
@@ -26,7 +26,7 @@ class Data(BaseModel):
address: Optional[str] = None
- billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode")
+ billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode")
cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd")
@@ -38,6 +38,8 @@ class Data(BaseModel):
current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
+ domain_id: Optional[str] = FieldInfo(alias="domainId", default=None)
+
inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages")
label: Optional[str] = None
diff --git a/src/mobilerun_sdk/types/mailbox_retrieve_response.py b/src/mobilerun_sdk/types/mailbox_retrieve_response.py
index efb60e24..ed490495 100644
--- a/src/mobilerun_sdk/types/mailbox_retrieve_response.py
+++ b/src/mobilerun_sdk/types/mailbox_retrieve_response.py
@@ -26,7 +26,7 @@ class Data(BaseModel):
address: Optional[str] = None
- billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode")
+ billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode")
cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd")
@@ -38,6 +38,8 @@ class Data(BaseModel):
current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
+ domain_id: Optional[str] = FieldInfo(alias="domainId", default=None)
+
inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages")
label: Optional[str] = None
diff --git a/src/mobilerun_sdk/types/mailbox_uncancel_response.py b/src/mobilerun_sdk/types/mailbox_uncancel_response.py
index 04688b3b..fc6b588e 100644
--- a/src/mobilerun_sdk/types/mailbox_uncancel_response.py
+++ b/src/mobilerun_sdk/types/mailbox_uncancel_response.py
@@ -26,7 +26,7 @@ class Data(BaseModel):
address: Optional[str] = None
- billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode")
+ billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode")
cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd")
@@ -38,6 +38,8 @@ class Data(BaseModel):
current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
+ domain_id: Optional[str] = FieldInfo(alias="domainId", default=None)
+
inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages")
label: Optional[str] = None
diff --git a/src/mobilerun_sdk/types/mailbox_update_response.py b/src/mobilerun_sdk/types/mailbox_update_response.py
index 893d9928..99de186b 100644
--- a/src/mobilerun_sdk/types/mailbox_update_response.py
+++ b/src/mobilerun_sdk/types/mailbox_update_response.py
@@ -26,7 +26,7 @@ class Data(BaseModel):
address: Optional[str] = None
- billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode")
+ billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode")
cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd")
@@ -38,6 +38,8 @@ class Data(BaseModel):
current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None)
+ domain_id: Optional[str] = FieldInfo(alias="domainId", default=None)
+
inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages")
label: Optional[str] = None
diff --git a/src/mobilerun_sdk/types/number_capacity_params.py b/src/mobilerun_sdk/types/number_capacity_params.py
new file mode 100644
index 00000000..a574c248
--- /dev/null
+++ b/src/mobilerun_sdk/types/number_capacity_params.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["NumberCapacityParams"]
+
+
+class NumberCapacityParams(TypedDict, total=False):
+ country: Required[str]
+ """ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries."""
diff --git a/src/mobilerun_sdk/types/number_capacity_response.py b/src/mobilerun_sdk/types/number_capacity_response.py
new file mode 100644
index 00000000..49d9e6ba
--- /dev/null
+++ b/src/mobilerun_sdk/types/number_capacity_response.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+
+__all__ = ["NumberCapacityResponse", "Data"]
+
+
+class Data(BaseModel):
+ included: int
+
+ included_remaining: int = FieldInfo(alias="includedRemaining")
+ """Deprecated — always equal to `remaining`.
+
+ Migrate to `remaining`; this field will be removed in a future revision.
+ """
+
+ remaining: int
+
+ status: Literal["available", "exhausted", "not_included"]
+
+
+class NumberCapacityResponse(BaseModel):
+ data: Data
diff --git a/src/mobilerun_sdk/types/number_create_params.py b/src/mobilerun_sdk/types/number_create_params.py
index 6098fc62..353cd5fb 100644
--- a/src/mobilerun_sdk/types/number_create_params.py
+++ b/src/mobilerun_sdk/types/number_create_params.py
@@ -11,14 +11,14 @@
class NumberCreateParams(TypedDict, total=False):
- billing_preference: Annotated[Literal["included", "rent"], PropertyInfo(alias="billingPreference")]
+ billing_preference: Annotated[Literal["included", "included_only", "rent"], PropertyInfo(alias="billingPreference")]
"""
- Prefer a free package seat ('included', default) or force the paid checkout
- ('rent')
+ Use included capacity when available, require included capacity without paid
+ fallback (included_only), or start a paid checkout (rent).
"""
country: str
- """Optional ISO 3166-1 alpha-2 country code from GET /numbers/countries.
+ """Optional ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries.
Cannot be combined with `purpose`.
"""
@@ -31,7 +31,7 @@ class NumberCreateParams(TypedDict, total=False):
"""
purpose: str
- """Optional Mobilerun Phone purpose slug from GET /numbers/purposes."""
+ """Optional purpose from GET /numbers/phones/purposes."""
idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")]
"""Optional request idempotency key."""
diff --git a/src/mobilerun_sdk/types/task_get_status_response.py b/src/mobilerun_sdk/types/task_get_status_response.py
index 4446b3bb..0e0f823c 100644
--- a/src/mobilerun_sdk/types/task_get_status_response.py
+++ b/src/mobilerun_sdk/types/task_get_status_response.py
@@ -33,7 +33,7 @@ class Execution(BaseModel):
class TaskGetStatusResponse(BaseModel):
- status: Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]
+ status: Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]
"""The status of the task"""
execution: Optional[Execution] = None
@@ -48,6 +48,12 @@ class TaskGetStatusResponse(BaseModel):
output: Optional[Dict[str, object]] = None
"""Structured output if outputSchema was set"""
+ recording_device_id: Optional[str] = FieldInfo(alias="recordingDeviceId", default=None)
+ """Device ID associated with recordingId"""
+
+ recording_id: Optional[str] = FieldInfo(alias="recordingId", default=None)
+ """ID of the task's whole-task video recording, if recordingEnabled was set"""
+
steps: Optional[int] = None
"""Number of steps taken"""
diff --git a/src/mobilerun_sdk/types/task_list_params.py b/src/mobilerun_sdk/types/task_list_params.py
index 044f84ad..1b08553e 100644
--- a/src/mobilerun_sdk/types/task_list_params.py
+++ b/src/mobilerun_sdk/types/task_list_params.py
@@ -28,4 +28,9 @@ class TaskListParams(TypedDict, total=False):
query: Optional[str]
"""Search in task description."""
- status: Optional[Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]]
+ source: Optional[Literal["api", "agent"]]
+ """Only tasks created via the API ('api') or spawned by an agent step ('agent')."""
+
+ status: Optional[
+ Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]
+ ]
diff --git a/src/mobilerun_sdk/types/task_list_response.py b/src/mobilerun_sdk/types/task_list_response.py
index 20a9744c..06fa4a46 100644
--- a/src/mobilerun_sdk/types/task_list_response.py
+++ b/src/mobilerun_sdk/types/task_list_response.py
@@ -32,7 +32,7 @@ class Item(BaseModel):
owner_id: str = FieldInfo(alias="ownerId")
- status: Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]
+ status: Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]
task: str
@@ -43,8 +43,6 @@ class Item(BaseModel):
accessibility: Optional[bool] = None
- agent_id: Optional[int] = FieldInfo(alias="agentId", default=None)
-
apps: Optional[List[str]] = None
cancel_requested_at: Optional[datetime] = FieldInfo(alias="cancelRequestedAt", default=None)
@@ -82,6 +80,20 @@ class Item(BaseModel):
reasoning: Optional[bool] = None
+ recording_device_id: Optional[str] = FieldInfo(alias="recordingDeviceId", default=None)
+
+ recording_enabled: Optional[bool] = FieldInfo(alias="recordingEnabled", default=None)
+ """Record device video for the whole task and persist a retrievable reference"""
+
+ recording_id: Optional[str] = FieldInfo(alias="recordingId", default=None)
+
+ source: Optional[Literal["api", "agent"]] = None
+ """
+ Where the task came from: 'api' for tasks created via POST /tasks, 'agent' for
+ tasks spawned by an agent step. Agent tasks are readable (status, trajectory,
+ media) but not controllable via this API.
+ """
+
stealth: Optional[bool] = None
steps: Optional[int] = None
@@ -94,6 +106,7 @@ class Item(BaseModel):
succeeded: Optional[bool] = None
temperature: Optional[float] = None
+ """Deprecated and ignored. Sampling behavior is controlled by the model provider."""
updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
diff --git a/src/mobilerun_sdk/types/task_retrieve_response.py b/src/mobilerun_sdk/types/task_retrieve_response.py
index 85887f56..95306e62 100644
--- a/src/mobilerun_sdk/types/task_retrieve_response.py
+++ b/src/mobilerun_sdk/types/task_retrieve_response.py
@@ -31,7 +31,7 @@ class Task(BaseModel):
owner_id: str = FieldInfo(alias="ownerId")
- status: Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]
+ status: Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]
task: str
@@ -42,8 +42,6 @@ class Task(BaseModel):
accessibility: Optional[bool] = None
- agent_id: Optional[int] = FieldInfo(alias="agentId", default=None)
-
apps: Optional[List[str]] = None
cancel_requested_at: Optional[datetime] = FieldInfo(alias="cancelRequestedAt", default=None)
@@ -81,6 +79,20 @@ class Task(BaseModel):
reasoning: Optional[bool] = None
+ recording_device_id: Optional[str] = FieldInfo(alias="recordingDeviceId", default=None)
+
+ recording_enabled: Optional[bool] = FieldInfo(alias="recordingEnabled", default=None)
+ """Record device video for the whole task and persist a retrievable reference"""
+
+ recording_id: Optional[str] = FieldInfo(alias="recordingId", default=None)
+
+ source: Optional[Literal["api", "agent"]] = None
+ """
+ Where the task came from: 'api' for tasks created via POST /tasks, 'agent' for
+ tasks spawned by an agent step. Agent tasks are readable (status, trajectory,
+ media) but not controllable via this API.
+ """
+
stealth: Optional[bool] = None
steps: Optional[int] = None
@@ -93,6 +105,7 @@ class Task(BaseModel):
succeeded: Optional[bool] = None
temperature: Optional[float] = None
+ """Deprecated and ignored. Sampling behavior is controlled by the model provider."""
updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
diff --git a/src/mobilerun_sdk/types/task_run_params.py b/src/mobilerun_sdk/types/task_run_params.py
index b66cf98f..ab090746 100644
--- a/src/mobilerun_sdk/types/task_run_params.py
+++ b/src/mobilerun_sdk/types/task_run_params.py
@@ -19,8 +19,6 @@ class TaskRunParams(TypedDict, total=False):
accessibility: bool
- agent_id: Annotated[int, PropertyInfo(alias="agentId")]
-
apps: SequenceNotStr[str]
continue_on_failure: Annotated[bool, PropertyInfo(alias="continueOnFailure")]
@@ -35,7 +33,7 @@ class TaskRunParams(TypedDict, total=False):
files: SequenceNotStr[str]
llm_model: Annotated[str, PropertyInfo(alias="llmModel")]
- """The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash')"""
+ """The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna')"""
max_steps: Annotated[int, PropertyInfo(alias="maxSteps")]
@@ -46,12 +44,22 @@ class TaskRunParams(TypedDict, total=False):
reasoning: bool
+ recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")]
+ """Record device video for the whole task and persist a retrievable reference"""
+
stealth: bool
subagent_model: Annotated[str, PropertyInfo(alias="subagentModel")]
"""LLM model used by sub-agent roles: executor, app_opener, structured_output"""
+ system_prompt: Annotated[Optional[str], PropertyInfo(alias="systemPrompt")]
+ """
+ Optional custom behavioral overlay applied on top of the agent's default system
+ prompts. Never echoed back in responses or errors.
+ """
+
temperature: float
+ """Deprecated and ignored. Sampling behavior is controlled by the model provider."""
vision: bool
diff --git a/src/mobilerun_sdk/types/task_run_response.py b/src/mobilerun_sdk/types/task_run_response.py
index 5987ba3d..6b402a65 100644
--- a/src/mobilerun_sdk/types/task_run_response.py
+++ b/src/mobilerun_sdk/types/task_run_response.py
@@ -14,7 +14,7 @@ class TaskRunResponse(BaseModel):
id: str
"""The ID of the task"""
- status: Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]
+ status: Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]
"""The status of the task (queued or created)"""
stream_url: Optional[str] = FieldInfo(alias="streamUrl", default=None)
diff --git a/src/mobilerun_sdk/types/task_run_streamed_params.py b/src/mobilerun_sdk/types/task_run_streamed_params.py
index 2522d16b..a25065bc 100644
--- a/src/mobilerun_sdk/types/task_run_streamed_params.py
+++ b/src/mobilerun_sdk/types/task_run_streamed_params.py
@@ -19,8 +19,6 @@ class TaskRunStreamedParams(TypedDict, total=False):
accessibility: bool
- agent_id: Annotated[int, PropertyInfo(alias="agentId")]
-
apps: SequenceNotStr[str]
continue_on_failure: Annotated[bool, PropertyInfo(alias="continueOnFailure")]
@@ -35,7 +33,7 @@ class TaskRunStreamedParams(TypedDict, total=False):
files: SequenceNotStr[str]
llm_model: Annotated[str, PropertyInfo(alias="llmModel")]
- """The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash')"""
+ """The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna')"""
max_steps: Annotated[int, PropertyInfo(alias="maxSteps")]
@@ -46,12 +44,22 @@ class TaskRunStreamedParams(TypedDict, total=False):
reasoning: bool
+ recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")]
+ """Record device video for the whole task and persist a retrievable reference"""
+
stealth: bool
subagent_model: Annotated[str, PropertyInfo(alias="subagentModel")]
"""LLM model used by sub-agent roles: executor, app_opener, structured_output"""
+ system_prompt: Annotated[Optional[str], PropertyInfo(alias="systemPrompt")]
+ """
+ Optional custom behavioral overlay applied on top of the agent's default system
+ prompts. Never echoed back in responses or errors.
+ """
+
temperature: float
+ """Deprecated and ignored. Sampling behavior is controlled by the model provider."""
vision: bool
diff --git a/src/mobilerun_sdk/types/webhook_event_types_response.py b/src/mobilerun_sdk/types/webhook_event_types_response.py
index 2d1d9e2f..9c7439d7 100644
--- a/src/mobilerun_sdk/types/webhook_event_types_response.py
+++ b/src/mobilerun_sdk/types/webhook_event_types_response.py
@@ -1,6 +1,6 @@
# 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
@@ -17,6 +17,8 @@ class DataSourceEventSurfaces(BaseModel):
webhook: bool
+ agent: Optional[bool] = None
+
class DataSourceEvent(BaseModel):
description: str
diff --git a/src/mobilerun_sdk/types/workflows/__init__.py b/src/mobilerun_sdk/types/workflows/__init__.py
index d9ae0f73..1de48081 100644
--- a/src/mobilerun_sdk/types/workflows/__init__.py
+++ b/src/mobilerun_sdk/types/workflows/__init__.py
@@ -32,6 +32,7 @@
from .action_delete_response import ActionDeleteResponse as ActionDeleteResponse
from .action_update_response import ActionUpdateResponse as ActionUpdateResponse
from .event_dry_run_response import EventDryRunResponse as EventDryRunResponse
+from .flow_capacity_response import FlowCapacityResponse as FlowCapacityResponse
from .flow_retrieve_response import FlowRetrieveResponse as FlowRetrieveResponse
from .timezone_list_response import TimezoneListResponse as TimezoneListResponse
from .execution_list_response import ExecutionListResponse as ExecutionListResponse
diff --git a/src/mobilerun_sdk/types/workflows/event_dry_run_response.py b/src/mobilerun_sdk/types/workflows/event_dry_run_response.py
index b04779e3..e7bb6eee 100644
--- a/src/mobilerun_sdk/types/workflows/event_dry_run_response.py
+++ b/src/mobilerun_sdk/types/workflows/event_dry_run_response.py
@@ -13,6 +13,7 @@
"DataMatchedFlow",
"DataMatchedFlowAction",
"DataMatchedFlowFlow",
+ "DataMatchedFlowFlowRecordingPolicy",
"DataMatchedFlowGates",
"DataMatchedFlowTrigger",
"DataValidation",
@@ -23,10 +24,14 @@
class DataMatchedFlowAction(BaseModel):
continue_on_error: bool = FieldInfo(alias="continueOnError")
+ flow_action_id: str = FieldInfo(alias="flowActionId")
+
method: str
name: str
+ recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+
service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"]
children: Optional[List[object]] = None
@@ -38,9 +43,15 @@ class DataMatchedFlowAction(BaseModel):
params: Optional[Dict[str, object]] = None
+class DataMatchedFlowFlowRecordingPolicy(BaseModel):
+ mode: Literal["off", "flow", "selected_steps"]
+
+
class DataMatchedFlowFlow(BaseModel):
id: str
+ archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None)
+
blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None)
consecutive_failures: int = FieldInfo(alias="consecutiveFailures")
@@ -58,6 +69,10 @@ class DataMatchedFlowFlow(BaseModel):
device_ids: List[str] = FieldInfo(alias="deviceIds")
enabled: bool
+ """
+ Compatibility projection of lifecycleStatus; true only when lifecycleStatus is
+ enabled.
+ """
health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled")
@@ -69,6 +84,8 @@ class DataMatchedFlowFlow(BaseModel):
last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None)
+ lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus")
+
name: str
notify_on_failure: bool = FieldInfo(alias="notifyOnFailure")
@@ -80,6 +97,12 @@ class DataMatchedFlowFlow(BaseModel):
owner_id: str = FieldInfo(alias="ownerId")
recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+ """
+ Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" =
+ recordingEnabled=false).
+ """
+
+ recording_policy: DataMatchedFlowFlowRecordingPolicy = FieldInfo(alias="recordingPolicy")
self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled")
diff --git a/src/mobilerun_sdk/types/workflows/execution_list_response.py b/src/mobilerun_sdk/types/workflows/execution_list_response.py
index b7c4993f..2a01709f 100644
--- a/src/mobilerun_sdk/types/workflows/execution_list_response.py
+++ b/src/mobilerun_sdk/types/workflows/execution_list_response.py
@@ -8,7 +8,37 @@
from ..._models import BaseModel
from ..shared.pagination import Pagination
-__all__ = ["ExecutionListResponse", "Item"]
+__all__ = ["ExecutionListResponse", "Item", "ItemRecording"]
+
+
+class ItemRecording(BaseModel):
+ id: str
+
+ attempt: int
+
+ child_index: int = FieldInfo(alias="childIndex")
+
+ flow_action_id: Optional[str] = FieldInfo(alias="flowActionId", default=None)
+
+ iteration_index: int = FieldInfo(alias="iterationIndex")
+
+ last_error: Optional[str] = FieldInfo(alias="lastError", default=None)
+
+ parent_index: int = FieldInfo(alias="parentIndex")
+
+ recording_device_id: Optional[str] = FieldInfo(alias="recordingDeviceId", default=None)
+
+ recording_id: Optional[str] = FieldInfo(alias="recordingId", default=None)
+
+ scope: Literal["flow", "step"]
+
+ started_at: Optional[str] = FieldInfo(alias="startedAt", default=None)
+
+ status: Literal["starting", "recording", "stopping", "stopped", "failed"]
+
+ step_index: int = FieldInfo(alias="stepIndex")
+
+ stopped_at: Optional[str] = FieldInfo(alias="stoppedAt", default=None)
class Item(BaseModel):
@@ -37,6 +67,12 @@ class Item(BaseModel):
the recording failed to start.
"""
+ recordings: List[ItemRecording]
+ """Durable recording segments ordered by step/loop coordinate and retry attempt.
+
+ Whole-flow recordings use -1 for every coordinate.
+ """
+
started_at: Optional[str] = FieldInfo(alias="startedAt", default=None)
status: Optional[Literal["pending", "running", "success", "failed", "cancelled", "skipped", "invalid"]] = None
diff --git a/src/mobilerun_sdk/types/workflows/execution_retrieve_response.py b/src/mobilerun_sdk/types/workflows/execution_retrieve_response.py
index de6c2d19..cda1e5ff 100644
--- a/src/mobilerun_sdk/types/workflows/execution_retrieve_response.py
+++ b/src/mobilerun_sdk/types/workflows/execution_retrieve_response.py
@@ -7,7 +7,7 @@
from ..._models import BaseModel
-__all__ = ["ExecutionRetrieveResponse", "Data", "DataFile"]
+__all__ = ["ExecutionRetrieveResponse", "Data", "DataFile", "DataRecording"]
class DataFile(BaseModel):
@@ -20,6 +20,36 @@ class DataFile(BaseModel):
size_bytes: int = FieldInfo(alias="sizeBytes")
+class DataRecording(BaseModel):
+ id: str
+
+ attempt: int
+
+ child_index: int = FieldInfo(alias="childIndex")
+
+ flow_action_id: Optional[str] = FieldInfo(alias="flowActionId", default=None)
+
+ iteration_index: int = FieldInfo(alias="iterationIndex")
+
+ last_error: Optional[str] = FieldInfo(alias="lastError", default=None)
+
+ parent_index: int = FieldInfo(alias="parentIndex")
+
+ recording_device_id: Optional[str] = FieldInfo(alias="recordingDeviceId", default=None)
+
+ recording_id: Optional[str] = FieldInfo(alias="recordingId", default=None)
+
+ scope: Literal["flow", "step"]
+
+ started_at: Optional[str] = FieldInfo(alias="startedAt", default=None)
+
+ status: Literal["starting", "recording", "stopping", "stopped", "failed"]
+
+ step_index: int = FieldInfo(alias="stepIndex")
+
+ stopped_at: Optional[str] = FieldInfo(alias="stoppedAt", default=None)
+
+
class Data(BaseModel):
id: str
@@ -53,6 +83,12 @@ class Data(BaseModel):
the recording failed to start.
"""
+ recordings: List[DataRecording]
+ """Durable recording segments ordered by step/loop coordinate and retry attempt.
+
+ Whole-flow recordings use -1 for every coordinate.
+ """
+
started_at: Optional[str] = FieldInfo(alias="startedAt", default=None)
status: Optional[Literal["pending", "running", "success", "failed", "cancelled", "skipped", "invalid"]] = None
diff --git a/src/mobilerun_sdk/types/workflows/flow_capacity_response.py b/src/mobilerun_sdk/types/workflows/flow_capacity_response.py
new file mode 100644
index 00000000..c101de72
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_capacity_response.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["FlowCapacityResponse", "Data"]
+
+
+class Data(BaseModel):
+ included: int
+
+ remaining: int
+
+ status: Literal["available", "exhausted", "not_included"]
+
+
+class FlowCapacityResponse(BaseModel):
+ data: Data
diff --git a/src/mobilerun_sdk/types/workflows/flow_clone_response.py b/src/mobilerun_sdk/types/workflows/flow_clone_response.py
index 14ed8d1f..e08b73dd 100644
--- a/src/mobilerun_sdk/types/workflows/flow_clone_response.py
+++ b/src/mobilerun_sdk/types/workflows/flow_clone_response.py
@@ -7,12 +7,18 @@
from ..._models import BaseModel
-__all__ = ["FlowCloneResponse", "Data"]
+__all__ = ["FlowCloneResponse", "Data", "DataRecordingPolicy"]
+
+
+class DataRecordingPolicy(BaseModel):
+ mode: Literal["off", "flow", "selected_steps"]
class Data(BaseModel):
id: str
+ archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None)
+
blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None)
consecutive_failures: int = FieldInfo(alias="consecutiveFailures")
@@ -30,6 +36,10 @@ class Data(BaseModel):
device_ids: List[str] = FieldInfo(alias="deviceIds")
enabled: bool
+ """
+ Compatibility projection of lifecycleStatus; true only when lifecycleStatus is
+ enabled.
+ """
health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled")
@@ -41,6 +51,8 @@ class Data(BaseModel):
last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None)
+ lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus")
+
name: str
notify_on_failure: bool = FieldInfo(alias="notifyOnFailure")
@@ -52,6 +64,12 @@ class Data(BaseModel):
owner_id: str = FieldInfo(alias="ownerId")
recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+ """
+ Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" =
+ recordingEnabled=false).
+ """
+
+ recording_policy: DataRecordingPolicy = FieldInfo(alias="recordingPolicy")
self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled")
diff --git a/src/mobilerun_sdk/types/workflows/flow_create_params.py b/src/mobilerun_sdk/types/workflows/flow_create_params.py
index cde7b202..1a292cf5 100644
--- a/src/mobilerun_sdk/types/workflows/flow_create_params.py
+++ b/src/mobilerun_sdk/types/workflows/flow_create_params.py
@@ -8,7 +8,7 @@
from ..._types import SequenceNotStr
from ..._utils import PropertyInfo
-__all__ = ["FlowCreateParams", "Action", "ActionChild", "ActionChildOverrides", "ActionOverrides"]
+__all__ = ["FlowCreateParams", "Action", "ActionChild", "ActionChildOverrides", "ActionOverrides", "RecordingPolicy"]
class FlowCreateParams(TypedDict, total=False):
@@ -37,6 +37,12 @@ class FlowCreateParams(TypedDict, total=False):
notify_webhook_id: Annotated[Optional[str], PropertyInfo(alias="notifyWebhookId")]
recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")]
+ """Deprecated compatibility field.
+
+ true maps to recordingPolicy.mode="flow"; false maps to "off".
+ """
+
+ recording_policy: Annotated[RecordingPolicy, PropertyInfo(alias="recordingPolicy")]
self_healing_enabled: Annotated[bool, PropertyInfo(alias="selfHealingEnabled")]
@@ -58,6 +64,8 @@ class ActionChild(TypedDict, total=False):
overrides: Optional[ActionChildOverrides]
+ recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")]
+
class ActionOverrides(TypedDict, total=False):
params: Dict[str, object]
@@ -75,3 +83,9 @@ class Action(TypedDict, total=False):
name_override: Annotated[str, PropertyInfo(alias="nameOverride")]
overrides: Optional[ActionOverrides]
+
+ recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")]
+
+
+class RecordingPolicy(TypedDict, total=False):
+ mode: Required[Literal["off", "flow", "selected_steps"]]
diff --git a/src/mobilerun_sdk/types/workflows/flow_create_response.py b/src/mobilerun_sdk/types/workflows/flow_create_response.py
index a840cf45..d4129117 100644
--- a/src/mobilerun_sdk/types/workflows/flow_create_response.py
+++ b/src/mobilerun_sdk/types/workflows/flow_create_response.py
@@ -7,12 +7,18 @@
from ..._models import BaseModel
-__all__ = ["FlowCreateResponse", "Data"]
+__all__ = ["FlowCreateResponse", "Data", "DataRecordingPolicy"]
+
+
+class DataRecordingPolicy(BaseModel):
+ mode: Literal["off", "flow", "selected_steps"]
class Data(BaseModel):
id: str
+ archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None)
+
blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None)
consecutive_failures: int = FieldInfo(alias="consecutiveFailures")
@@ -30,6 +36,10 @@ class Data(BaseModel):
device_ids: List[str] = FieldInfo(alias="deviceIds")
enabled: bool
+ """
+ Compatibility projection of lifecycleStatus; true only when lifecycleStatus is
+ enabled.
+ """
health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled")
@@ -41,6 +51,8 @@ class Data(BaseModel):
last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None)
+ lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus")
+
name: str
notify_on_failure: bool = FieldInfo(alias="notifyOnFailure")
@@ -52,6 +64,12 @@ class Data(BaseModel):
owner_id: str = FieldInfo(alias="ownerId")
recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+ """
+ Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" =
+ recordingEnabled=false).
+ """
+
+ recording_policy: DataRecordingPolicy = FieldInfo(alias="recordingPolicy")
self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled")
diff --git a/src/mobilerun_sdk/types/workflows/flow_dry_run_response.py b/src/mobilerun_sdk/types/workflows/flow_dry_run_response.py
index d9a5bf30..5592add2 100644
--- a/src/mobilerun_sdk/types/workflows/flow_dry_run_response.py
+++ b/src/mobilerun_sdk/types/workflows/flow_dry_run_response.py
@@ -13,10 +13,14 @@
class DataAction(BaseModel):
continue_on_error: bool = FieldInfo(alias="continueOnError")
+ flow_action_id: str = FieldInfo(alias="flowActionId")
+
method: str
name: str
+ recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+
service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"]
children: Optional[List[object]] = None
diff --git a/src/mobilerun_sdk/types/workflows/flow_list_response.py b/src/mobilerun_sdk/types/workflows/flow_list_response.py
index 5cd546ab..01705f9f 100644
--- a/src/mobilerun_sdk/types/workflows/flow_list_response.py
+++ b/src/mobilerun_sdk/types/workflows/flow_list_response.py
@@ -8,12 +8,18 @@
from ..._models import BaseModel
from ..shared.pagination import Pagination
-__all__ = ["FlowListResponse", "Item"]
+__all__ = ["FlowListResponse", "Item", "ItemRecordingPolicy"]
+
+
+class ItemRecordingPolicy(BaseModel):
+ mode: Literal["off", "flow", "selected_steps"]
class Item(BaseModel):
id: str
+ archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None)
+
blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None)
consecutive_failures: int = FieldInfo(alias="consecutiveFailures")
@@ -31,6 +37,10 @@ class Item(BaseModel):
device_ids: List[str] = FieldInfo(alias="deviceIds")
enabled: bool
+ """
+ Compatibility projection of lifecycleStatus; true only when lifecycleStatus is
+ enabled.
+ """
health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled")
@@ -42,6 +52,8 @@ class Item(BaseModel):
last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None)
+ lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus")
+
name: str
notify_on_failure: bool = FieldInfo(alias="notifyOnFailure")
@@ -53,6 +65,12 @@ class Item(BaseModel):
owner_id: str = FieldInfo(alias="ownerId")
recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+ """
+ Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" =
+ recordingEnabled=false).
+ """
+
+ recording_policy: ItemRecordingPolicy = FieldInfo(alias="recordingPolicy")
self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled")
diff --git a/src/mobilerun_sdk/types/workflows/flow_retrieve_response.py b/src/mobilerun_sdk/types/workflows/flow_retrieve_response.py
index dab4caa9..b4cd5806 100644
--- a/src/mobilerun_sdk/types/workflows/flow_retrieve_response.py
+++ b/src/mobilerun_sdk/types/workflows/flow_retrieve_response.py
@@ -7,12 +7,18 @@
from ..._models import BaseModel
-__all__ = ["FlowRetrieveResponse", "Data"]
+__all__ = ["FlowRetrieveResponse", "Data", "DataRecordingPolicy"]
+
+
+class DataRecordingPolicy(BaseModel):
+ mode: Literal["off", "flow", "selected_steps"]
class Data(BaseModel):
id: str
+ archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None)
+
blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None)
consecutive_failures: int = FieldInfo(alias="consecutiveFailures")
@@ -30,6 +36,10 @@ class Data(BaseModel):
device_ids: List[str] = FieldInfo(alias="deviceIds")
enabled: bool
+ """
+ Compatibility projection of lifecycleStatus; true only when lifecycleStatus is
+ enabled.
+ """
health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled")
@@ -41,6 +51,8 @@ class Data(BaseModel):
last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None)
+ lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus")
+
name: str
notify_on_failure: bool = FieldInfo(alias="notifyOnFailure")
@@ -52,6 +64,12 @@ class Data(BaseModel):
owner_id: str = FieldInfo(alias="ownerId")
recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+ """
+ Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" =
+ recordingEnabled=false).
+ """
+
+ recording_policy: DataRecordingPolicy = FieldInfo(alias="recordingPolicy")
self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled")
diff --git a/src/mobilerun_sdk/types/workflows/flow_unblock_response.py b/src/mobilerun_sdk/types/workflows/flow_unblock_response.py
index 0429bba4..d71392de 100644
--- a/src/mobilerun_sdk/types/workflows/flow_unblock_response.py
+++ b/src/mobilerun_sdk/types/workflows/flow_unblock_response.py
@@ -7,12 +7,18 @@
from ..._models import BaseModel
-__all__ = ["FlowUnblockResponse", "Data"]
+__all__ = ["FlowUnblockResponse", "Data", "DataRecordingPolicy"]
+
+
+class DataRecordingPolicy(BaseModel):
+ mode: Literal["off", "flow", "selected_steps"]
class Data(BaseModel):
id: str
+ archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None)
+
blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None)
consecutive_failures: int = FieldInfo(alias="consecutiveFailures")
@@ -30,6 +36,10 @@ class Data(BaseModel):
device_ids: List[str] = FieldInfo(alias="deviceIds")
enabled: bool
+ """
+ Compatibility projection of lifecycleStatus; true only when lifecycleStatus is
+ enabled.
+ """
health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled")
@@ -41,6 +51,8 @@ class Data(BaseModel):
last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None)
+ lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus")
+
name: str
notify_on_failure: bool = FieldInfo(alias="notifyOnFailure")
@@ -52,6 +64,12 @@ class Data(BaseModel):
owner_id: str = FieldInfo(alias="ownerId")
recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+ """
+ Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" =
+ recordingEnabled=false).
+ """
+
+ recording_policy: DataRecordingPolicy = FieldInfo(alias="recordingPolicy")
self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled")
diff --git a/src/mobilerun_sdk/types/workflows/flow_update_params.py b/src/mobilerun_sdk/types/workflows/flow_update_params.py
index 8db31b2e..9f32e4bb 100644
--- a/src/mobilerun_sdk/types/workflows/flow_update_params.py
+++ b/src/mobilerun_sdk/types/workflows/flow_update_params.py
@@ -3,12 +3,12 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Literal, Annotated, TypedDict
+from typing_extensions import Literal, Required, Annotated, TypedDict
from ..._types import SequenceNotStr
from ..._utils import PropertyInfo
-__all__ = ["FlowUpdateParams"]
+__all__ = ["FlowUpdateParams", "RecordingPolicy"]
class FlowUpdateParams(TypedDict, total=False):
@@ -24,6 +24,9 @@ class FlowUpdateParams(TypedDict, total=False):
health_monitoring_enabled: Annotated[bool, PropertyInfo(alias="healthMonitoringEnabled")]
+ lifecycle_status: Annotated[Literal["enabled", "disabled"], PropertyInfo(alias="lifecycleStatus")]
+ """Set the visible agent lifecycle. Archive remains available only through DELETE."""
+
name: str
notify_on_failure: Annotated[bool, PropertyInfo(alias="notifyOnFailure")]
@@ -33,9 +36,19 @@ class FlowUpdateParams(TypedDict, total=False):
notify_webhook_id: Annotated[Optional[str], PropertyInfo(alias="notifyWebhookId")]
recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")]
+ """Deprecated compatibility field.
+
+ true maps to recordingPolicy.mode="flow"; false maps to "off".
+ """
+
+ recording_policy: Annotated[RecordingPolicy, PropertyInfo(alias="recordingPolicy")]
self_healing_enabled: Annotated[bool, PropertyInfo(alias="selfHealingEnabled")]
self_healing_max_attempts: Annotated[int, PropertyInfo(alias="selfHealingMaxAttempts")]
trigger_id: Annotated[str, PropertyInfo(alias="triggerId")]
+
+
+class RecordingPolicy(TypedDict, total=False):
+ mode: Required[Literal["off", "flow", "selected_steps"]]
diff --git a/src/mobilerun_sdk/types/workflows/flow_update_response.py b/src/mobilerun_sdk/types/workflows/flow_update_response.py
index ad10348f..511e934a 100644
--- a/src/mobilerun_sdk/types/workflows/flow_update_response.py
+++ b/src/mobilerun_sdk/types/workflows/flow_update_response.py
@@ -7,12 +7,18 @@
from ..._models import BaseModel
-__all__ = ["FlowUpdateResponse", "Data"]
+__all__ = ["FlowUpdateResponse", "Data", "DataRecordingPolicy"]
+
+
+class DataRecordingPolicy(BaseModel):
+ mode: Literal["off", "flow", "selected_steps"]
class Data(BaseModel):
id: str
+ archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None)
+
blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None)
consecutive_failures: int = FieldInfo(alias="consecutiveFailures")
@@ -30,6 +36,10 @@ class Data(BaseModel):
device_ids: List[str] = FieldInfo(alias="deviceIds")
enabled: bool
+ """
+ Compatibility projection of lifecycleStatus; true only when lifecycleStatus is
+ enabled.
+ """
health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled")
@@ -41,6 +51,8 @@ class Data(BaseModel):
last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None)
+ lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus")
+
name: str
notify_on_failure: bool = FieldInfo(alias="notifyOnFailure")
@@ -52,6 +64,12 @@ class Data(BaseModel):
owner_id: str = FieldInfo(alias="ownerId")
recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+ """
+ Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" =
+ recordingEnabled=false).
+ """
+
+ recording_policy: DataRecordingPolicy = FieldInfo(alias="recordingPolicy")
self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled")
diff --git a/src/mobilerun_sdk/types/workflows/flows/action_add_params.py b/src/mobilerun_sdk/types/workflows/flows/action_add_params.py
index 1275209c..88af2ccf 100644
--- a/src/mobilerun_sdk/types/workflows/flows/action_add_params.py
+++ b/src/mobilerun_sdk/types/workflows/flows/action_add_params.py
@@ -25,6 +25,8 @@ class ActionAddParams(TypedDict, total=False):
parent_flow_action_id: Annotated[Optional[str], PropertyInfo(alias="parentFlowActionId")]
+ recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")]
+
class ChildOverrides(TypedDict, total=False):
params: Dict[str, object]
@@ -41,6 +43,8 @@ class Child(TypedDict, total=False):
overrides: Optional[ChildOverrides]
+ recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")]
+
class Overrides(TypedDict, total=False):
params: Dict[str, object]
diff --git a/src/mobilerun_sdk/types/workflows/flows/action_add_response.py b/src/mobilerun_sdk/types/workflows/flows/action_add_response.py
index 00d02c81..420a30e5 100644
--- a/src/mobilerun_sdk/types/workflows/flows/action_add_response.py
+++ b/src/mobilerun_sdk/types/workflows/flows/action_add_response.py
@@ -32,6 +32,12 @@ class Data(BaseModel):
position: int
+ recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+ """
+ Selected for per-step recording under the flow's "selected_steps" recording
+ policy.
+ """
+
class ActionAddResponse(BaseModel):
data: Data
diff --git a/src/mobilerun_sdk/types/workflows/flows/action_list_response.py b/src/mobilerun_sdk/types/workflows/flows/action_list_response.py
index 88c4965b..1ff8dd43 100644
--- a/src/mobilerun_sdk/types/workflows/flows/action_list_response.py
+++ b/src/mobilerun_sdk/types/workflows/flows/action_list_response.py
@@ -32,6 +32,12 @@ class Data(BaseModel):
position: int
+ recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+ """
+ Selected for per-step recording under the flow's "selected_steps" recording
+ policy.
+ """
+
class ActionListResponse(BaseModel):
data: List[Data]
diff --git a/src/mobilerun_sdk/types/workflows/flows/action_replace_params.py b/src/mobilerun_sdk/types/workflows/flows/action_replace_params.py
index ec5c42a1..fd89af25 100644
--- a/src/mobilerun_sdk/types/workflows/flows/action_replace_params.py
+++ b/src/mobilerun_sdk/types/workflows/flows/action_replace_params.py
@@ -29,6 +29,8 @@ class ActionChild(TypedDict, total=False):
overrides: Optional[ActionChildOverrides]
+ recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")]
+
class ActionOverrides(TypedDict, total=False):
params: Dict[str, object]
@@ -46,3 +48,5 @@ class Action(TypedDict, total=False):
name_override: Annotated[str, PropertyInfo(alias="nameOverride")]
overrides: Optional[ActionOverrides]
+
+ recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")]
diff --git a/src/mobilerun_sdk/types/workflows/flows/action_replace_response.py b/src/mobilerun_sdk/types/workflows/flows/action_replace_response.py
index cf358f90..a9939a84 100644
--- a/src/mobilerun_sdk/types/workflows/flows/action_replace_response.py
+++ b/src/mobilerun_sdk/types/workflows/flows/action_replace_response.py
@@ -32,6 +32,12 @@ class Data(BaseModel):
position: int
+ recording_enabled: bool = FieldInfo(alias="recordingEnabled")
+ """
+ Selected for per-step recording under the flow's "selected_steps" recording
+ policy.
+ """
+
class ActionReplaceResponse(BaseModel):
data: List[Data]
diff --git a/tests/api_resources/connect/test_proxies.py b/tests/api_resources/connect/test_proxies.py
index acd84195..f2e62efb 100644
--- a/tests/api_resources/connect/test_proxies.py
+++ b/tests/api_resources/connect/test_proxies.py
@@ -113,6 +113,16 @@ def test_method_buy(self, client: Mobilerun) -> None:
)
assert_matches_type(ProxyBuyResponse, proxy, path=["response"])
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_buy_with_all_params(self, client: Mobilerun) -> None:
+ proxy = client.connect.proxies.buy(
+ country="country",
+ type="dedicated_residential",
+ idempotency_key="Idempotency-Key",
+ )
+ assert_matches_type(ProxyBuyResponse, proxy, path=["response"])
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_raw_response_buy(self, client: Mobilerun) -> None:
@@ -395,6 +405,16 @@ async def test_method_buy(self, async_client: AsyncMobilerun) -> None:
)
assert_matches_type(ProxyBuyResponse, proxy, path=["response"])
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_buy_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ proxy = await async_client.connect.proxies.buy(
+ country="country",
+ type="dedicated_residential",
+ idempotency_key="Idempotency-Key",
+ )
+ assert_matches_type(ProxyBuyResponse, proxy, path=["response"])
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_raw_response_buy(self, async_client: AsyncMobilerun) -> None:
diff --git a/tests/api_resources/devices/test_apps.py b/tests/api_resources/devices/test_apps.py
index c1281d68..aa3726ed 100644
--- a/tests/api_resources/devices/test_apps.py
+++ b/tests/api_resources/devices/test_apps.py
@@ -219,7 +219,9 @@ def test_method_install_with_all_params_overload_1(self, client: Mobilerun) -> N
device_id="deviceId",
bundle_id="x",
background=True,
+ country="se",
package_name="x",
+ version_code=1,
x_device_display_id=0,
)
assert app is None
@@ -278,6 +280,8 @@ def test_method_install_with_all_params_overload_2(self, client: Mobilerun) -> N
package_name="x",
background=True,
bundle_id="x",
+ country="se",
+ version_code=1,
x_device_display_id=0,
)
assert app is None
@@ -769,7 +773,9 @@ async def test_method_install_with_all_params_overload_1(self, async_client: Asy
device_id="deviceId",
bundle_id="x",
background=True,
+ country="se",
package_name="x",
+ version_code=1,
x_device_display_id=0,
)
assert app is None
@@ -828,6 +834,8 @@ async def test_method_install_with_all_params_overload_2(self, async_client: Asy
package_name="x",
background=True,
bundle_id="x",
+ country="se",
+ version_code=1,
x_device_display_id=0,
)
assert app is None
diff --git a/tests/api_resources/devices/test_keyboard.py b/tests/api_resources/devices/test_keyboard.py
index 766a63b8..29044ca3 100644
--- a/tests/api_resources/devices/test_keyboard.py
+++ b/tests/api_resources/devices/test_keyboard.py
@@ -138,6 +138,7 @@ def test_method_write_with_all_params(self, client: Mobilerun) -> None:
device_id="deviceId",
text="text",
clear=True,
+ completion_mode="accepted",
error_rate=0,
stealth=True,
wpm=0,
@@ -311,6 +312,7 @@ async def test_method_write_with_all_params(self, async_client: AsyncMobilerun)
device_id="deviceId",
text="text",
clear=True,
+ completion_mode="accepted",
error_rate=0,
stealth=True,
wpm=0,
diff --git a/tests/api_resources/devices/test_recordings.py b/tests/api_resources/devices/test_recordings.py
index f3e134fb..4d72e541 100644
--- a/tests/api_resources/devices/test_recordings.py
+++ b/tests/api_resources/devices/test_recordings.py
@@ -140,6 +140,7 @@ def test_method_start_with_all_params(self, client: Mobilerun) -> None:
recording = client.devices.recordings.start(
device_id="deviceId",
name="name",
+ quality=1,
retention_days=1,
types=["string"],
)
@@ -511,6 +512,7 @@ async def test_method_start_with_all_params(self, async_client: AsyncMobilerun)
recording = await async_client.devices.recordings.start(
device_id="deviceId",
name="name",
+ quality=1,
retention_days=1,
types=["string"],
)
diff --git a/tests/api_resources/devices/test_traffic_sessions.py b/tests/api_resources/devices/test_traffic_sessions.py
new file mode 100644
index 00000000..458eddf1
--- /dev/null
+++ b/tests/api_resources/devices/test_traffic_sessions.py
@@ -0,0 +1,455 @@
+# 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 tests.utils import assert_matches_type
+from mobilerun_sdk import Mobilerun, AsyncMobilerun
+from mobilerun_sdk.types.devices import (
+ TrafficSessionListResponse,
+ TrafficSessionCreateResponse,
+ TrafficSessionDeleteResponse,
+ TrafficSessionRetrieveResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestTrafficSessions:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create(self, client: Mobilerun) -> None:
+ traffic_session = client.devices.traffic_sessions.create(
+ device_id="deviceId",
+ idempotency_key="x",
+ )
+ assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Mobilerun) -> None:
+ traffic_session = client.devices.traffic_sessions.create(
+ device_id="deviceId",
+ idempotency_key="x",
+ expires_in_seconds=60,
+ max_body_bytes=0,
+ )
+ assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Mobilerun) -> None:
+ response = client.devices.traffic_sessions.with_raw_response.create(
+ device_id="deviceId",
+ idempotency_key="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ traffic_session = response.parse()
+ assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Mobilerun) -> None:
+ with client.devices.traffic_sessions.with_streaming_response.create(
+ device_id="deviceId",
+ idempotency_key="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ traffic_session = response.parse()
+ assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_create(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
+ client.devices.traffic_sessions.with_raw_response.create(
+ device_id="",
+ idempotency_key="x",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve(self, client: Mobilerun) -> None:
+ traffic_session = client.devices.traffic_sessions.retrieve(
+ session_id="sessionId",
+ device_id="deviceId",
+ )
+ assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Mobilerun) -> None:
+ response = client.devices.traffic_sessions.with_raw_response.retrieve(
+ session_id="sessionId",
+ device_id="deviceId",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ traffic_session = response.parse()
+ assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Mobilerun) -> None:
+ with client.devices.traffic_sessions.with_streaming_response.retrieve(
+ session_id="sessionId",
+ device_id="deviceId",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ traffic_session = response.parse()
+ assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_retrieve(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
+ client.devices.traffic_sessions.with_raw_response.retrieve(
+ session_id="sessionId",
+ device_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
+ client.devices.traffic_sessions.with_raw_response.retrieve(
+ session_id="",
+ device_id="deviceId",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Mobilerun) -> None:
+ traffic_session = client.devices.traffic_sessions.list(
+ device_id="deviceId",
+ )
+ assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mobilerun) -> None:
+ traffic_session = client.devices.traffic_sessions.list(
+ device_id="deviceId",
+ page=1,
+ page_size=1,
+ )
+ assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.devices.traffic_sessions.with_raw_response.list(
+ device_id="deviceId",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ traffic_session = response.parse()
+ assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.devices.traffic_sessions.with_streaming_response.list(
+ device_id="deviceId",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ traffic_session = response.parse()
+ assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_list(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
+ client.devices.traffic_sessions.with_raw_response.list(
+ device_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_delete(self, client: Mobilerun) -> None:
+ traffic_session = client.devices.traffic_sessions.delete(
+ session_id="sessionId",
+ device_id="deviceId",
+ )
+ assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete(self, client: Mobilerun) -> None:
+ response = client.devices.traffic_sessions.with_raw_response.delete(
+ session_id="sessionId",
+ device_id="deviceId",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ traffic_session = response.parse()
+ assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete(self, client: Mobilerun) -> None:
+ with client.devices.traffic_sessions.with_streaming_response.delete(
+ session_id="sessionId",
+ device_id="deviceId",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ traffic_session = response.parse()
+ assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_delete(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
+ client.devices.traffic_sessions.with_raw_response.delete(
+ session_id="sessionId",
+ device_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
+ client.devices.traffic_sessions.with_raw_response.delete(
+ session_id="",
+ device_id="deviceId",
+ )
+
+
+class TestAsyncTrafficSessions:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_create(self, async_client: AsyncMobilerun) -> None:
+ traffic_session = await async_client.devices.traffic_sessions.create(
+ device_id="deviceId",
+ idempotency_key="x",
+ )
+ assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ traffic_session = await async_client.devices.traffic_sessions.create(
+ device_id="deviceId",
+ idempotency_key="x",
+ expires_in_seconds=60,
+ max_body_bytes=0,
+ )
+ assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.devices.traffic_sessions.with_raw_response.create(
+ device_id="deviceId",
+ idempotency_key="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ traffic_session = await response.parse()
+ assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.devices.traffic_sessions.with_streaming_response.create(
+ device_id="deviceId",
+ idempotency_key="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ traffic_session = await response.parse()
+ assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_create(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
+ await async_client.devices.traffic_sessions.with_raw_response.create(
+ device_id="",
+ idempotency_key="x",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncMobilerun) -> None:
+ traffic_session = await async_client.devices.traffic_sessions.retrieve(
+ session_id="sessionId",
+ device_id="deviceId",
+ )
+ assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.devices.traffic_sessions.with_raw_response.retrieve(
+ session_id="sessionId",
+ device_id="deviceId",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ traffic_session = await response.parse()
+ assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.devices.traffic_sessions.with_streaming_response.retrieve(
+ session_id="sessionId",
+ device_id="deviceId",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ traffic_session = await response.parse()
+ assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
+ await async_client.devices.traffic_sessions.with_raw_response.retrieve(
+ session_id="sessionId",
+ device_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
+ await async_client.devices.traffic_sessions.with_raw_response.retrieve(
+ session_id="",
+ device_id="deviceId",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncMobilerun) -> None:
+ traffic_session = await async_client.devices.traffic_sessions.list(
+ device_id="deviceId",
+ )
+ assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ traffic_session = await async_client.devices.traffic_sessions.list(
+ device_id="deviceId",
+ page=1,
+ page_size=1,
+ )
+ assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.devices.traffic_sessions.with_raw_response.list(
+ device_id="deviceId",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ traffic_session = await response.parse()
+ assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.devices.traffic_sessions.with_streaming_response.list(
+ device_id="deviceId",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ traffic_session = await response.parse()
+ assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_list(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
+ await async_client.devices.traffic_sessions.with_raw_response.list(
+ device_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncMobilerun) -> None:
+ traffic_session = await async_client.devices.traffic_sessions.delete(
+ session_id="sessionId",
+ device_id="deviceId",
+ )
+ assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_delete(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.devices.traffic_sessions.with_raw_response.delete(
+ session_id="sessionId",
+ device_id="deviceId",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ traffic_session = await response.parse()
+ assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_delete(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.devices.traffic_sessions.with_streaming_response.delete(
+ session_id="sessionId",
+ device_id="deviceId",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ traffic_session = await response.parse()
+ assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_delete(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
+ await async_client.devices.traffic_sessions.with_raw_response.delete(
+ session_id="sessionId",
+ device_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
+ await async_client.devices.traffic_sessions.with_raw_response.delete(
+ session_id="",
+ device_id="deviceId",
+ )
diff --git a/tests/api_resources/esims/__init__.py b/tests/api_resources/esims/__init__.py
deleted file mode 100644
index fd8019a9..00000000
--- a/tests/api_resources/esims/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/esims/test_messages.py b/tests/api_resources/esims/test_messages.py
deleted file mode 100644
index aa71f91d..00000000
--- a/tests/api_resources/esims/test_messages.py
+++ /dev/null
@@ -1,262 +0,0 @@
-# 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 tests.utils import assert_matches_type
-from mobilerun_sdk import Mobilerun, AsyncMobilerun
-from mobilerun_sdk.types.esims import MessageListResponse, MessageSendResponse
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestMessages:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_list(self, client: Mobilerun) -> None:
- message = client.esims.messages.list(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(MessageListResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_list_with_all_params(self, client: Mobilerun) -> None:
- message = client.esims.messages.list(
- id="550e8400-e29b-41d4-a716-446655440000",
- direction="all",
- number_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- page=1,
- page_size=1,
- peer_key="x",
- peer_number="xxx",
- status="all",
- )
- assert_matches_type(MessageListResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_list(self, client: Mobilerun) -> None:
- response = client.esims.messages.with_raw_response.list(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- message = response.parse()
- assert_matches_type(MessageListResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_list(self, client: Mobilerun) -> None:
- with client.esims.messages.with_streaming_response.list(
- id="550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- message = response.parse()
- assert_matches_type(MessageListResponse, message, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_list(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- client.esims.messages.with_raw_response.list(
- id="",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_send(self, client: Mobilerun) -> None:
- message = client.esims.messages.send(
- id="550e8400-e29b-41d4-a716-446655440000",
- body="x",
- to="+15551230001",
- )
- assert_matches_type(MessageSendResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_send_with_all_params(self, client: Mobilerun) -> None:
- message = client.esims.messages.send(
- id="550e8400-e29b-41d4-a716-446655440000",
- body="x",
- to="+15551230001",
- client_request_id="x",
- delivery_report=True,
- )
- assert_matches_type(MessageSendResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_send(self, client: Mobilerun) -> None:
- response = client.esims.messages.with_raw_response.send(
- id="550e8400-e29b-41d4-a716-446655440000",
- body="x",
- to="+15551230001",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- message = response.parse()
- assert_matches_type(MessageSendResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_send(self, client: Mobilerun) -> None:
- with client.esims.messages.with_streaming_response.send(
- id="550e8400-e29b-41d4-a716-446655440000",
- body="x",
- to="+15551230001",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- message = response.parse()
- assert_matches_type(MessageSendResponse, message, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_send(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- client.esims.messages.with_raw_response.send(
- id="",
- body="x",
- to="+15551230001",
- )
-
-
-class TestAsyncMessages:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_list(self, async_client: AsyncMobilerun) -> None:
- message = await async_client.esims.messages.list(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(MessageListResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncMobilerun) -> None:
- message = await async_client.esims.messages.list(
- id="550e8400-e29b-41d4-a716-446655440000",
- direction="all",
- number_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- page=1,
- page_size=1,
- peer_key="x",
- peer_number="xxx",
- status="all",
- )
- assert_matches_type(MessageListResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_list(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.messages.with_raw_response.list(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- message = await response.parse()
- assert_matches_type(MessageListResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_list(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.messages.with_streaming_response.list(
- id="550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- message = await response.parse()
- assert_matches_type(MessageListResponse, message, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_list(self, async_client: AsyncMobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- await async_client.esims.messages.with_raw_response.list(
- id="",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_send(self, async_client: AsyncMobilerun) -> None:
- message = await async_client.esims.messages.send(
- id="550e8400-e29b-41d4-a716-446655440000",
- body="x",
- to="+15551230001",
- )
- assert_matches_type(MessageSendResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_send_with_all_params(self, async_client: AsyncMobilerun) -> None:
- message = await async_client.esims.messages.send(
- id="550e8400-e29b-41d4-a716-446655440000",
- body="x",
- to="+15551230001",
- client_request_id="x",
- delivery_report=True,
- )
- assert_matches_type(MessageSendResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_send(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.messages.with_raw_response.send(
- id="550e8400-e29b-41d4-a716-446655440000",
- body="x",
- to="+15551230001",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- message = await response.parse()
- assert_matches_type(MessageSendResponse, message, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_send(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.messages.with_streaming_response.send(
- id="550e8400-e29b-41d4-a716-446655440000",
- body="x",
- to="+15551230001",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- message = await response.parse()
- assert_matches_type(MessageSendResponse, message, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_send(self, async_client: AsyncMobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- await async_client.esims.messages.with_raw_response.send(
- id="",
- body="x",
- to="+15551230001",
- )
diff --git a/tests/api_resources/test_esims.py b/tests/api_resources/test_esims.py
deleted file mode 100644
index a47275d3..00000000
--- a/tests/api_resources/test_esims.py
+++ /dev/null
@@ -1,953 +0,0 @@
-# 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 tests.utils import assert_matches_type
-from mobilerun_sdk import Mobilerun, AsyncMobilerun
-from mobilerun_sdk.types import (
- EsimListResponse,
- EsimCreateResponse,
- EsimImportResponse,
- EsimUpdateResponse,
- EsimInstallResponse,
- EsimCapacityResponse,
- EsimRetrieveResponse,
- EsimSelectorResponse,
- EsimInstallStatusResponse,
- EsimConfirmPaymentResponse,
-)
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestEsims:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_create(self, client: Mobilerun) -> None:
- esim = client.esims.create()
- assert_matches_type(EsimCreateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_create_with_all_params(self, client: Mobilerun) -> None:
- esim = client.esims.create(
- idempotency_key="idempotencyKey",
- name="Mom's phone",
- )
- assert_matches_type(EsimCreateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_create(self, client: Mobilerun) -> None:
- response = client.esims.with_raw_response.create()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert_matches_type(EsimCreateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_create(self, client: Mobilerun) -> None:
- with client.esims.with_streaming_response.create() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert_matches_type(EsimCreateResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_retrieve(self, client: Mobilerun) -> None:
- esim = client.esims.retrieve(
- "550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(EsimRetrieveResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_retrieve(self, client: Mobilerun) -> None:
- response = client.esims.with_raw_response.retrieve(
- "550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert_matches_type(EsimRetrieveResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_retrieve(self, client: Mobilerun) -> None:
- with client.esims.with_streaming_response.retrieve(
- "550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert_matches_type(EsimRetrieveResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_retrieve(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- client.esims.with_raw_response.retrieve(
- "",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_update(self, client: Mobilerun) -> None:
- esim = client.esims.update(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(EsimUpdateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_update_with_all_params(self, client: Mobilerun) -> None:
- esim = client.esims.update(
- id="550e8400-e29b-41d4-a716-446655440000",
- msisdn="+33612345678",
- name="Mom's phone",
- )
- assert_matches_type(EsimUpdateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_update(self, client: Mobilerun) -> None:
- response = client.esims.with_raw_response.update(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert_matches_type(EsimUpdateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_update(self, client: Mobilerun) -> None:
- with client.esims.with_streaming_response.update(
- id="550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert_matches_type(EsimUpdateResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_update(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- client.esims.with_raw_response.update(
- id="",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_list(self, client: Mobilerun) -> None:
- esim = client.esims.list()
- assert_matches_type(EsimListResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_list_with_all_params(self, client: Mobilerun) -> None:
- esim = client.esims.list(
- mine="true",
- page=1,
- page_size=1,
- status="all",
- )
- assert_matches_type(EsimListResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_list(self, client: Mobilerun) -> None:
- response = client.esims.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert_matches_type(EsimListResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_list(self, client: Mobilerun) -> None:
- with client.esims.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert_matches_type(EsimListResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_delete(self, client: Mobilerun) -> None:
- esim = client.esims.delete(
- "550e8400-e29b-41d4-a716-446655440000",
- )
- assert esim is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_delete(self, client: Mobilerun) -> None:
- response = client.esims.with_raw_response.delete(
- "550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert esim is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_delete(self, client: Mobilerun) -> None:
- with client.esims.with_streaming_response.delete(
- "550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert esim is None
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_delete(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- client.esims.with_raw_response.delete(
- "",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_capacity(self, client: Mobilerun) -> None:
- esim = client.esims.capacity()
- assert_matches_type(EsimCapacityResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_capacity(self, client: Mobilerun) -> None:
- response = client.esims.with_raw_response.capacity()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert_matches_type(EsimCapacityResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_capacity(self, client: Mobilerun) -> None:
- with client.esims.with_streaming_response.capacity() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert_matches_type(EsimCapacityResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_confirm_payment(self, client: Mobilerun) -> None:
- esim = client.esims.confirm_payment(
- "550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_confirm_payment(self, client: Mobilerun) -> None:
- response = client.esims.with_raw_response.confirm_payment(
- "550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_confirm_payment(self, client: Mobilerun) -> None:
- with client.esims.with_streaming_response.confirm_payment(
- "550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_confirm_payment(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- client.esims.with_raw_response.confirm_payment(
- "",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_import(self, client: Mobilerun) -> None:
- esim = client.esims.import_()
- assert_matches_type(EsimImportResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_import_with_all_params(self, client: Mobilerun) -> None:
- esim = client.esims.import_(
- auto_install=True,
- carrier_name="carrierName",
- confirmation_code="confirmationCode",
- country_code="countryCode",
- device_id="physedge-dev-8f3a2c",
- idempotency_key="x",
- lpa_code="LPA:1$smdp.example.com$QR-MATCH-1",
- matching_id="matchingId",
- msisdn="+33612345678",
- name="Mom's phone",
- notes="notes",
- smdp_address="smdp.example.com",
- )
- assert_matches_type(EsimImportResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_import(self, client: Mobilerun) -> None:
- response = client.esims.with_raw_response.import_()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert_matches_type(EsimImportResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_import(self, client: Mobilerun) -> None:
- with client.esims.with_streaming_response.import_() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert_matches_type(EsimImportResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_install(self, client: Mobilerun) -> None:
- esim = client.esims.install(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(EsimInstallResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_install_with_all_params(self, client: Mobilerun) -> None:
- esim = client.esims.install(
- id="550e8400-e29b-41d4-a716-446655440000",
- device_id="physedge-dev-8f3a2c",
- )
- assert_matches_type(EsimInstallResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_install(self, client: Mobilerun) -> None:
- response = client.esims.with_raw_response.install(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert_matches_type(EsimInstallResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_install(self, client: Mobilerun) -> None:
- with client.esims.with_streaming_response.install(
- id="550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert_matches_type(EsimInstallResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_install(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- client.esims.with_raw_response.install(
- id="",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_install_status(self, client: Mobilerun) -> None:
- esim = client.esims.install_status(
- "550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(EsimInstallStatusResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_install_status(self, client: Mobilerun) -> None:
- response = client.esims.with_raw_response.install_status(
- "550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert_matches_type(EsimInstallStatusResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_install_status(self, client: Mobilerun) -> None:
- with client.esims.with_streaming_response.install_status(
- "550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert_matches_type(EsimInstallStatusResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_install_status(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- client.esims.with_raw_response.install_status(
- "",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_selector(self, client: Mobilerun) -> None:
- esim = client.esims.selector()
- assert_matches_type(EsimSelectorResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_selector_with_all_params(self, client: Mobilerun) -> None:
- esim = client.esims.selector(
- page=1,
- page_size=1,
- )
- assert_matches_type(EsimSelectorResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_selector(self, client: Mobilerun) -> None:
- response = client.esims.with_raw_response.selector()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert_matches_type(EsimSelectorResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_selector(self, client: Mobilerun) -> None:
- with client.esims.with_streaming_response.selector() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert_matches_type(EsimSelectorResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncEsims:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_create(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.create()
- assert_matches_type(EsimCreateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_create_with_all_params(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.create(
- idempotency_key="idempotencyKey",
- name="Mom's phone",
- )
- assert_matches_type(EsimCreateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_create(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.with_raw_response.create()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert_matches_type(EsimCreateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_create(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.with_streaming_response.create() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert_matches_type(EsimCreateResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_retrieve(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.retrieve(
- "550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(EsimRetrieveResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_retrieve(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.with_raw_response.retrieve(
- "550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert_matches_type(EsimRetrieveResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_retrieve(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.with_streaming_response.retrieve(
- "550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert_matches_type(EsimRetrieveResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_retrieve(self, async_client: AsyncMobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- await async_client.esims.with_raw_response.retrieve(
- "",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_update(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.update(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(EsimUpdateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_update_with_all_params(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.update(
- id="550e8400-e29b-41d4-a716-446655440000",
- msisdn="+33612345678",
- name="Mom's phone",
- )
- assert_matches_type(EsimUpdateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_update(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.with_raw_response.update(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert_matches_type(EsimUpdateResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_update(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.with_streaming_response.update(
- id="550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert_matches_type(EsimUpdateResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_update(self, async_client: AsyncMobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- await async_client.esims.with_raw_response.update(
- id="",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_list(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.list()
- assert_matches_type(EsimListResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.list(
- mine="true",
- page=1,
- page_size=1,
- status="all",
- )
- assert_matches_type(EsimListResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_list(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert_matches_type(EsimListResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_list(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert_matches_type(EsimListResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_delete(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.delete(
- "550e8400-e29b-41d4-a716-446655440000",
- )
- assert esim is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_delete(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.with_raw_response.delete(
- "550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert esim is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_delete(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.with_streaming_response.delete(
- "550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert esim is None
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_delete(self, async_client: AsyncMobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- await async_client.esims.with_raw_response.delete(
- "",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_capacity(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.capacity()
- assert_matches_type(EsimCapacityResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_capacity(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.with_raw_response.capacity()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert_matches_type(EsimCapacityResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_capacity(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.with_streaming_response.capacity() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert_matches_type(EsimCapacityResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_confirm_payment(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.confirm_payment(
- "550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_confirm_payment(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.with_raw_response.confirm_payment(
- "550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_confirm_payment(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.with_streaming_response.confirm_payment(
- "550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_confirm_payment(self, async_client: AsyncMobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- await async_client.esims.with_raw_response.confirm_payment(
- "",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_import(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.import_()
- assert_matches_type(EsimImportResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_import_with_all_params(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.import_(
- auto_install=True,
- carrier_name="carrierName",
- confirmation_code="confirmationCode",
- country_code="countryCode",
- device_id="physedge-dev-8f3a2c",
- idempotency_key="x",
- lpa_code="LPA:1$smdp.example.com$QR-MATCH-1",
- matching_id="matchingId",
- msisdn="+33612345678",
- name="Mom's phone",
- notes="notes",
- smdp_address="smdp.example.com",
- )
- assert_matches_type(EsimImportResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_import(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.with_raw_response.import_()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert_matches_type(EsimImportResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_import(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.with_streaming_response.import_() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert_matches_type(EsimImportResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_install(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.install(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(EsimInstallResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_install_with_all_params(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.install(
- id="550e8400-e29b-41d4-a716-446655440000",
- device_id="physedge-dev-8f3a2c",
- )
- assert_matches_type(EsimInstallResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_install(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.with_raw_response.install(
- id="550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert_matches_type(EsimInstallResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_install(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.with_streaming_response.install(
- id="550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert_matches_type(EsimInstallResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_install(self, async_client: AsyncMobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- await async_client.esims.with_raw_response.install(
- id="",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_install_status(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.install_status(
- "550e8400-e29b-41d4-a716-446655440000",
- )
- assert_matches_type(EsimInstallStatusResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_install_status(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.with_raw_response.install_status(
- "550e8400-e29b-41d4-a716-446655440000",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert_matches_type(EsimInstallStatusResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_install_status(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.with_streaming_response.install_status(
- "550e8400-e29b-41d4-a716-446655440000",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert_matches_type(EsimInstallStatusResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_install_status(self, async_client: AsyncMobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- await async_client.esims.with_raw_response.install_status(
- "",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_selector(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.selector()
- assert_matches_type(EsimSelectorResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_selector_with_all_params(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.esims.selector(
- page=1,
- page_size=1,
- )
- assert_matches_type(EsimSelectorResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_selector(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.esims.with_raw_response.selector()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert_matches_type(EsimSelectorResponse, esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_selector(self, async_client: AsyncMobilerun) -> None:
- async with async_client.esims.with_streaming_response.selector() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert_matches_type(EsimSelectorResponse, esim, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py
index 47decef9..47e3feb7 100644
--- a/tests/api_resources/test_files.py
+++ b/tests/api_resources/test_files.py
@@ -10,10 +10,7 @@
from tests.utils import assert_matches_type
from mobilerun_sdk import Mobilerun, AsyncMobilerun
from mobilerun_sdk.types import (
- FileListResponse,
FileDeleteResponse,
- FileUpdateResponse,
- FileConfirmResponse,
FileUploadURLResponse,
FileCancelPendingResponse,
)
@@ -24,94 +21,6 @@
class TestFiles:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_update(self, client: Mobilerun) -> None:
- file = client.files.update(
- file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert_matches_type(FileUpdateResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_update_with_all_params(self, client: Mobilerun) -> None:
- file = client.files.update(
- file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- display_name="x",
- enabled=True,
- )
- assert_matches_type(FileUpdateResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_update(self, client: Mobilerun) -> None:
- response = client.files.with_raw_response.update(
- file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- file = response.parse()
- assert_matches_type(FileUpdateResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_update(self, client: Mobilerun) -> None:
- with client.files.with_streaming_response.update(
- file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- file = response.parse()
- assert_matches_type(FileUpdateResponse, file, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_update(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"):
- client.files.with_raw_response.update(
- file_id="",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_list(self, client: Mobilerun) -> None:
- file = client.files.list()
- assert_matches_type(FileListResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_list_with_all_params(self, client: Mobilerun) -> None:
- file = client.files.list(
- zone="user",
- )
- assert_matches_type(FileListResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_list(self, client: Mobilerun) -> None:
- response = client.files.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- file = response.parse()
- assert_matches_type(FileListResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_list(self, client: Mobilerun) -> None:
- with client.files.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- file = response.parse()
- assert_matches_type(FileListResponse, file, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_delete(self, client: Mobilerun) -> None:
@@ -196,48 +105,6 @@ def test_path_params_cancel_pending(self, client: Mobilerun) -> None:
"",
)
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_confirm(self, client: Mobilerun) -> None:
- file = client.files.confirm(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert_matches_type(FileConfirmResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_confirm(self, client: Mobilerun) -> None:
- response = client.files.with_raw_response.confirm(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- file = response.parse()
- assert_matches_type(FileConfirmResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_confirm(self, client: Mobilerun) -> None:
- with client.files.with_streaming_response.confirm(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- file = response.parse()
- assert_matches_type(FileConfirmResponse, file, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_confirm(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"):
- client.files.with_raw_response.confirm(
- "",
- )
-
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_download(self, client: Mobilerun) -> None:
@@ -338,94 +205,6 @@ class TestAsyncFiles:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_update(self, async_client: AsyncMobilerun) -> None:
- file = await async_client.files.update(
- file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert_matches_type(FileUpdateResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_update_with_all_params(self, async_client: AsyncMobilerun) -> None:
- file = await async_client.files.update(
- file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- display_name="x",
- enabled=True,
- )
- assert_matches_type(FileUpdateResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_update(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.files.with_raw_response.update(
- file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- file = await response.parse()
- assert_matches_type(FileUpdateResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_update(self, async_client: AsyncMobilerun) -> None:
- async with async_client.files.with_streaming_response.update(
- file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- file = await response.parse()
- assert_matches_type(FileUpdateResponse, file, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_update(self, async_client: AsyncMobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"):
- await async_client.files.with_raw_response.update(
- file_id="",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_list(self, async_client: AsyncMobilerun) -> None:
- file = await async_client.files.list()
- assert_matches_type(FileListResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncMobilerun) -> None:
- file = await async_client.files.list(
- zone="user",
- )
- assert_matches_type(FileListResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_list(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.files.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- file = await response.parse()
- assert_matches_type(FileListResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_list(self, async_client: AsyncMobilerun) -> None:
- async with async_client.files.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- file = await response.parse()
- assert_matches_type(FileListResponse, file, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_delete(self, async_client: AsyncMobilerun) -> None:
@@ -510,48 +289,6 @@ async def test_path_params_cancel_pending(self, async_client: AsyncMobilerun) ->
"",
)
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_confirm(self, async_client: AsyncMobilerun) -> None:
- file = await async_client.files.confirm(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert_matches_type(FileConfirmResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_confirm(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.files.with_raw_response.confirm(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- file = await response.parse()
- assert_matches_type(FileConfirmResponse, file, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_confirm(self, async_client: AsyncMobilerun) -> None:
- async with async_client.files.with_streaming_response.confirm(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- file = await response.parse()
- assert_matches_type(FileConfirmResponse, file, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_confirm(self, async_client: AsyncMobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"):
- await async_client.files.with_raw_response.confirm(
- "",
- )
-
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_download(self, async_client: AsyncMobilerun) -> None:
diff --git a/tests/api_resources/test_mailboxes.py b/tests/api_resources/test_mailboxes.py
index fee64e12..45d04734 100644
--- a/tests/api_resources/test_mailboxes.py
+++ b/tests/api_resources/test_mailboxes.py
@@ -42,6 +42,7 @@ def test_method_create_with_all_params(self, client: Mobilerun) -> None:
mailbox = client.mailboxes.create(
client_request_id="x",
billing_preference="included",
+ domain_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
label="label",
local_part="jane-doe",
)
@@ -435,6 +436,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncMobilerun)
mailbox = await async_client.mailboxes.create(
client_request_id="x",
billing_preference="included",
+ domain_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
label="label",
local_part="jane-doe",
)
diff --git a/tests/api_resources/test_numbers.py b/tests/api_resources/test_numbers.py
index 44193174..957aab3c 100644
--- a/tests/api_resources/test_numbers.py
+++ b/tests/api_resources/test_numbers.py
@@ -14,6 +14,7 @@
NumberCreateResponse,
NumberDeleteResponse,
NumberUpdateResponse,
+ NumberCapacityResponse,
NumberPurposesResponse,
NumberRetrieveResponse,
NumberCountriesResponse,
@@ -237,6 +238,40 @@ def test_path_params_delete(self, client: Mobilerun) -> None:
"",
)
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_capacity(self, client: Mobilerun) -> None:
+ number = client.numbers.capacity(
+ country="de",
+ )
+ assert_matches_type(NumberCapacityResponse, number, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_capacity(self, client: Mobilerun) -> None:
+ response = client.numbers.with_raw_response.capacity(
+ country="de",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ number = response.parse()
+ assert_matches_type(NumberCapacityResponse, number, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_capacity(self, client: Mobilerun) -> None:
+ with client.numbers.with_streaming_response.capacity(
+ country="de",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ number = response.parse()
+ assert_matches_type(NumberCapacityResponse, number, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_countries(self, client: Mobilerun) -> None:
@@ -511,6 +546,40 @@ async def test_path_params_delete(self, async_client: AsyncMobilerun) -> None:
"",
)
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_capacity(self, async_client: AsyncMobilerun) -> None:
+ number = await async_client.numbers.capacity(
+ country="de",
+ )
+ assert_matches_type(NumberCapacityResponse, number, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_capacity(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.numbers.with_raw_response.capacity(
+ country="de",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ number = await response.parse()
+ assert_matches_type(NumberCapacityResponse, number, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_capacity(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.numbers.with_streaming_response.capacity(
+ country="de",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ number = await response.parse()
+ assert_matches_type(NumberCapacityResponse, number, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_countries(self, async_client: AsyncMobilerun) -> None:
diff --git a/tests/api_resources/test_tasks.py b/tests/api_resources/test_tasks.py
index cf65f53d..9a7b6bee 100644
--- a/tests/api_resources/test_tasks.py
+++ b/tests/api_resources/test_tasks.py
@@ -84,7 +84,8 @@ def test_method_list_with_all_params(self, client: Mobilerun) -> None:
page=1,
page_size=1,
query="query",
- status="queued",
+ source="api",
+ status="prepared",
)
assert_matches_type(TaskListResponse, task, path=["response"])
@@ -252,7 +253,6 @@ def test_method_run_with_all_params(self, client: Mobilerun) -> None:
device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
task="x",
accessibility=True,
- agent_id=0,
apps=["string"],
continue_on_failure=True,
credentials=[
@@ -269,8 +269,10 @@ def test_method_run_with_all_params(self, client: Mobilerun) -> None:
memory_namespace="memoryNamespace",
output_schema={"foo": "bar"},
reasoning=True,
+ recording_enabled=True,
stealth=True,
subagent_model="subagentModel",
+ system_prompt="systemPrompt",
temperature=0,
vision=True,
vpn_country="US",
@@ -322,7 +324,6 @@ def test_method_run_streamed_with_all_params(self, client: Mobilerun) -> None:
device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
task="x",
accessibility=True,
- agent_id=0,
apps=["string"],
continue_on_failure=True,
credentials=[
@@ -339,8 +340,10 @@ def test_method_run_streamed_with_all_params(self, client: Mobilerun) -> None:
memory_namespace="memoryNamespace",
output_schema={"foo": "bar"},
reasoning=True,
+ recording_enabled=True,
stealth=True,
subagent_model="subagentModel",
+ system_prompt="systemPrompt",
temperature=0,
vision=True,
vpn_country="US",
@@ -528,7 +531,8 @@ async def test_method_list_with_all_params(self, async_client: AsyncMobilerun) -
page=1,
page_size=1,
query="query",
- status="queued",
+ source="api",
+ status="prepared",
)
assert_matches_type(TaskListResponse, task, path=["response"])
@@ -696,7 +700,6 @@ async def test_method_run_with_all_params(self, async_client: AsyncMobilerun) ->
device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
task="x",
accessibility=True,
- agent_id=0,
apps=["string"],
continue_on_failure=True,
credentials=[
@@ -713,8 +716,10 @@ async def test_method_run_with_all_params(self, async_client: AsyncMobilerun) ->
memory_namespace="memoryNamespace",
output_schema={"foo": "bar"},
reasoning=True,
+ recording_enabled=True,
stealth=True,
subagent_model="subagentModel",
+ system_prompt="systemPrompt",
temperature=0,
vision=True,
vpn_country="US",
@@ -766,7 +771,6 @@ async def test_method_run_streamed_with_all_params(self, async_client: AsyncMobi
device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
task="x",
accessibility=True,
- agent_id=0,
apps=["string"],
continue_on_failure=True,
credentials=[
@@ -783,8 +787,10 @@ async def test_method_run_streamed_with_all_params(self, async_client: AsyncMobi
memory_namespace="memoryNamespace",
output_schema={"foo": "bar"},
reasoning=True,
+ recording_enabled=True,
stealth=True,
subagent_model="subagentModel",
+ system_prompt="systemPrompt",
temperature=0,
vision=True,
vpn_country="US",
diff --git a/tests/api_resources/workflows/flows/test_actions.py b/tests/api_resources/workflows/flows/test_actions.py
index 797f7246..21f7ca88 100644
--- a/tests/api_resources/workflows/flows/test_actions.py
+++ b/tests/api_resources/workflows/flows/test_actions.py
@@ -88,12 +88,14 @@ def test_method_add_with_all_params(self, client: Mobilerun) -> None:
"continue_on_error": True,
"name_override": "x",
"overrides": {"params": {"foo": "bar"}},
+ "recording_enabled": True,
}
],
continue_on_error=True,
name_override="x",
overrides={"params": {"foo": "bar"}},
parent_flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ recording_enabled=True,
)
assert_matches_type(ActionAddResponse, action, path=["response"])
@@ -327,12 +329,14 @@ async def test_method_add_with_all_params(self, async_client: AsyncMobilerun) ->
"continue_on_error": True,
"name_override": "x",
"overrides": {"params": {"foo": "bar"}},
+ "recording_enabled": True,
}
],
continue_on_error=True,
name_override="x",
overrides={"params": {"foo": "bar"}},
parent_flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ recording_enabled=True,
)
assert_matches_type(ActionAddResponse, action, path=["response"])
diff --git a/tests/api_resources/workflows/test_flows.py b/tests/api_resources/workflows/test_flows.py
index 845d0f4f..eb527497 100644
--- a/tests/api_resources/workflows/test_flows.py
+++ b/tests/api_resources/workflows/test_flows.py
@@ -17,6 +17,7 @@
FlowDryRunResponse,
FlowUpdateResponse,
FlowUnblockResponse,
+ FlowCapacityResponse,
FlowRetrieveResponse,
FlowListRepairsResponse,
)
@@ -57,11 +58,13 @@ def test_method_create_with_all_params(self, client: Mobilerun) -> None:
"continue_on_error": True,
"name_override": "x",
"overrides": {"params": {"foo": "bar"}},
+ "recording_enabled": True,
}
],
"continue_on_error": True,
"name_override": "x",
"overrides": {"params": {"foo": "bar"}},
+ "recording_enabled": True,
}
],
name="x",
@@ -76,6 +79,7 @@ def test_method_create_with_all_params(self, client: Mobilerun) -> None:
notify_on_success=True,
notify_webhook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
recording_enabled=True,
+ recording_policy={"mode": "off"},
self_healing_enabled=True,
self_healing_max_attempts=1,
)
@@ -182,11 +186,13 @@ def test_method_update_with_all_params(self, client: Mobilerun) -> None:
device_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
enabled=True,
health_monitoring_enabled=True,
+ lifecycle_status="enabled",
name="x",
notify_on_failure=True,
notify_on_success=True,
notify_webhook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
recording_enabled=True,
+ recording_policy={"mode": "off"},
self_healing_enabled=True,
self_healing_max_attempts=1,
trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
@@ -314,6 +320,34 @@ def test_path_params_delete(self, client: Mobilerun) -> None:
"",
)
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_capacity(self, client: Mobilerun) -> None:
+ flow = client.workflows.flows.capacity()
+ assert_matches_type(FlowCapacityResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_capacity(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.with_raw_response.capacity()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = response.parse()
+ assert_matches_type(FlowCapacityResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_capacity(self, client: Mobilerun) -> None:
+ with client.workflows.flows.with_streaming_response.capacity() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = response.parse()
+ assert_matches_type(FlowCapacityResponse, flow, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_clone(self, client: Mobilerun) -> None:
@@ -537,11 +571,13 @@ async def test_method_create_with_all_params(self, async_client: AsyncMobilerun)
"continue_on_error": True,
"name_override": "x",
"overrides": {"params": {"foo": "bar"}},
+ "recording_enabled": True,
}
],
"continue_on_error": True,
"name_override": "x",
"overrides": {"params": {"foo": "bar"}},
+ "recording_enabled": True,
}
],
name="x",
@@ -556,6 +592,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncMobilerun)
notify_on_success=True,
notify_webhook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
recording_enabled=True,
+ recording_policy={"mode": "off"},
self_healing_enabled=True,
self_healing_max_attempts=1,
)
@@ -662,11 +699,13 @@ async def test_method_update_with_all_params(self, async_client: AsyncMobilerun)
device_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
enabled=True,
health_monitoring_enabled=True,
+ lifecycle_status="enabled",
name="x",
notify_on_failure=True,
notify_on_success=True,
notify_webhook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
recording_enabled=True,
+ recording_policy={"mode": "off"},
self_healing_enabled=True,
self_healing_max_attempts=1,
trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
@@ -794,6 +833,34 @@ async def test_path_params_delete(self, async_client: AsyncMobilerun) -> None:
"",
)
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_capacity(self, async_client: AsyncMobilerun) -> None:
+ flow = await async_client.workflows.flows.capacity()
+ assert_matches_type(FlowCapacityResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_capacity(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.flows.with_raw_response.capacity()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = await response.parse()
+ assert_matches_type(FlowCapacityResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_capacity(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.flows.with_streaming_response.capacity() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = await response.parse()
+ assert_matches_type(FlowCapacityResponse, flow, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_clone(self, async_client: AsyncMobilerun) -> None: