---
editLink: false
lastUpdated: false
outline: [2, 3]
---

<!-- Generated by python/b2c-tooling-sdk/scripts/generate_api_docs.py. Do not edit. -->

# b2c_tooling_sdk.operations.ods

ODS (On-Demand Sandbox) operations.

Mirrors `src/operations/ods/index.ts`.

## Classes

### BuildSandboxSettingsOptions {#buildsandboxsettingsoptions}

```python
class BuildSandboxSettingsOptions
```

Options for [`build_sandbox_settings`](/python/api/operations/ods#build-sandbox-settings).

**Fields**

| Name | Type | Default |
| --- | --- | --- |
| `client_id` | `str \| None` | `None` |
| `ocapi_settings` | `list[dict[str, Any]] \| None` | `None` |
| `webdav_settings` | `list[dict[str, Any]] \| None` | `None` |

### CloneBatchFailedError {#clonebatchfailederror}

```python
class CloneBatchFailedError(Exception)
```

Raised when one or more clones in a batch enter the `FAILED` state.

All clones in the batch reached a terminal state, but at least one of them failed.

### CloneBatchMemberStatus {#clonebatchmemberstatus}

```python
class CloneBatchMemberStatus
```

Status of a single clone within a batch, as observed on one poll tick.

**Fields**

| Name | Type | Default |
| --- | --- | --- |
| `clone_id` | `str` |  |
| `status` | `CloneState` |  |
| `progress_percentage` | `int \| None` | `None` |

### CloneBatchPollingError {#clonebatchpollingerror}

```python
class CloneBatchPollingError(Exception)
```

Raised when an API request to fetch the status of a clone in a batch fails.

### CloneBatchPollingTimeoutError {#clonebatchpollingtimeouterror}

```python
class CloneBatchPollingTimeoutError(Exception)
```

Raised when a batch of sandbox clones does not all reach a terminal state within the timeout.

### CloneFailedError {#clonefailederror}

```python
class CloneFailedError(Exception)
```

Raised when a sandbox clone operation enters the `FAILED` state.

### ClonePollingError {#clonepollingerror}

```python
class ClonePollingError(Exception)
```

Raised when an API request to fetch clone status fails.

### ClonePollingTimeoutError {#clonepollingtimeouterror}

```python
class ClonePollingTimeoutError(Exception)
```

Raised when a sandbox clone operation does not complete within the configured timeout while polling.

### SandboxNotFoundError {#sandboxnotfounderror}

```python
class SandboxNotFoundError(Exception)
```

Raised when a sandbox cannot be found by its friendly identifier.

### SandboxPollingError {#sandboxpollingerror}

```python
class SandboxPollingError(Exception)
```

Raised when fetching sandbox status fails during polling.

### SandboxPollingTimeoutError {#sandboxpollingtimeouterror}

```python
class SandboxPollingTimeoutError(Exception)
```

Raised when a sandbox does not reach its target state within the specified timeout period.

### SandboxTerminalStateError {#sandboxterminalstateerror}

```python
class SandboxTerminalStateError(Exception)
```

Raised when a sandbox reaches a terminal error state (failed or deleted) during polling.

### WaitForCloneOptions {#waitforcloneoptions}

```python
class WaitForCloneOptions
```

Configuration options for `wait_for_clone` polling behavior.

**Fields**

| Name | Type | Default |
| --- | --- | --- |
| `sandbox_id` | `str` |  |
| `clone_id` | `str` |  |
| `poll_interval_seconds` | `float` |  |
| `timeout_seconds` | `float` |  |
| `on_poll` | `Callable[[WaitForClonePollInfo], None] \| None` | `None` |
| `sleep` | `Callable[[float], Awaitable[None]]` | `_default_sleep` |

### WaitForClonePollInfo {#waitforclonepollinfo}

```python
class WaitForClonePollInfo
```

Information passed to the `on_poll` callback on each clone status poll.

**Fields**

| Name | Type | Default |
| --- | --- | --- |
| `sandbox_id` | `str` |  |
| `clone_id` | `str` |  |
| `elapsed_seconds` | `float` |  |
| `status` | `CloneState` |  |
| `progress_percentage` | `int \| None` | `None` |

### WaitForClonesOptions {#waitforclonesoptions}

```python
class WaitForClonesOptions
```

Configuration options for `wait_for_clones` batch polling behavior.

**Fields**

| Name | Type | Default |
| --- | --- | --- |
| `sandbox_id` | `str` |  |
| `clone_ids` | `list[str]` |  |
| `poll_interval_seconds` | `float` |  |
| `timeout_seconds` | `float` |  |
| `on_poll` | `Callable[[WaitForClonesPollInfo], None] \| None` | `None` |
| `sleep` | `Callable[[float], Awaitable[None]]` | `_default_sleep` |

### WaitForClonesPollInfo {#waitforclonespollinfo}

```python
class WaitForClonesPollInfo
```

Information passed to the `on_poll` callback on each poll tick while waiting for a batch of clones.

**Fields**

| Name | Type |
| --- | --- |
| `sandbox_id` | `str` |
| `elapsed_seconds` | `float` |
| `completed` | `int` |
| `total` | `int` |
| `clones` | `list[CloneBatchMemberStatus]` |

### WaitForSandboxOptions {#waitforsandboxoptions}

```python
class WaitForSandboxOptions
```

Configuration options for `wait_for_sandbox` sandbox state polling.

**Fields**

| Name | Type | Default |
| --- | --- | --- |
| `sandbox_id` | `str` |  |
| `target_state` | `SandboxState` |  |
| `poll_interval_seconds` | `float` |  |
| `timeout_seconds` | `float` |  |
| `on_poll` | `Callable[[WaitForSandboxPollInfo], None] \| None` | `None` |
| `sleep` | `Callable[[float], Awaitable[None]]` | `_default_sleep` |

### WaitForSandboxPollInfo {#waitforsandboxpollinfo}

```python
class WaitForSandboxPollInfo
```

Information provided to the `on_poll` callback on each poll during sandbox state monitoring.

**Fields**

| Name | Type |
| --- | --- |
| `sandbox_id` | `str` |
| `elapsed_seconds` | `float` |
| `state` | `SandboxState` |

## Functions

### build_sandbox_settings {#build-sandbox-settings}

```python
def build_sandbox_settings(options: BuildSandboxSettingsOptions) -> dict[str, Any] | None
```

Build the sandbox `settings` object granting OCAPI and WebDAV permissions to a client ID.

New sandboxes have no API permissions by default, so the client used to
create the sandbox (e.g. for code deployment) must be granted access
explicitly or subsequent operations will fail with authorization errors.

When `ocapi_settings`/`webdav_settings` are provided they fully replace
the defaults. Otherwise, when a `client_id` is provided, the client is
granted the default resources/permissions.

:example:
```python
>>> settings = build_sandbox_settings(BuildSandboxSettingsOptions(client_id=config.values.client_id))
>>> await ods_client.post("/sandboxes", {"body": {"realm": realm, "ttl": ttl, "settings": settings}})
```

**Parameters**

| Name | Type | Description |
| --- | --- | --- |
| `options` | `BuildSandboxSettingsOptions` | The settings to build. |

**Returns:** The settings dict, or `None` when there is nothing to set (no client ID and no custom settings).

### is_friendly_sandbox_id {#is-friendly-sandbox-id}

```python
def is_friendly_sandbox_id(value: str) -> bool
```

Check if a string matches the friendly sandbox ID format (realm-instance or realm_instance).

**Parameters**

| Name | Type | Description |
| --- | --- | --- |
| `value` | `str` | The string to check. |

**Returns:** `True` if the value matches the friendly format.

### is_uuid {#is-uuid}

```python
def is_uuid(value: str) -> bool
```

Check if a string is a valid UUID.

**Parameters**

| Name | Type | Description |
| --- | --- | --- |
| `value` | `str` | The string to check. |

**Returns:** `True` if the value is a valid UUID.

### parse_friendly_sandbox_id {#parse-friendly-sandbox-id}

```python
def parse_friendly_sandbox_id(value: str) -> ParsedFriendlySandboxId | None
```

Parse a friendly sandbox ID into its realm and instance components.

**Parameters**

| Name | Type | Description |
| --- | --- | --- |
| `value` | `str` | The friendly ID to parse (e.g., `"abcd-123"` or `"abcd_123"`). |

**Returns:** The parsed realm/instance, or `None` if not a valid friendly ID.

### resolve_sandbox_id {#resolve-sandbox-id}

```python
async def resolve_sandbox_id(client: OdsClient, identifier: str) -> str
```

Resolve a sandbox identifier to a UUID.

If the identifier is already a UUID, it is returned directly without making an
API call. If the identifier is a friendly format (realm-instance), it queries
the ODS API to find the matching sandbox and returns its UUID.

:example:
```python
>>> # UUID is returned directly
>>> await resolve_sandbox_id(client, "abc12345-1234-1234-1234-abc123456789")
'abc12345-1234-1234-1234-abc123456789'
>>> # Friendly ID is looked up
>>> await resolve_sandbox_id(client, "zzzv-123")
'abc12345-1234-1234-1234-abc123456789'  # actual UUID from API
```

**Parameters**

| Name | Type | Description |
| --- | --- | --- |
| `client` | `OdsClient` | The ODS API client. |
| `identifier` | `str` | Sandbox identifier (UUID or friendly format like `"abcd-123"`). |

**Returns:** The sandbox UUID.

**Raises**

- [`SandboxNotFoundError`](/python/api/operations/ods#sandboxnotfounderror) — If the sandbox cannot be found.

## Attributes

### DEFAULT_OCAPI_RESOURCES {#default-ocapi-resources}

```python
DEFAULT_OCAPI_RESOURCES: list[dict[str, Any]] = ...
```

### DEFAULT_WEBDAV_PERMISSIONS {#default-webdav-permissions}

```python
DEFAULT_WEBDAV_PERMISSIONS: list[dict[str, Any]] = [{'path': '/impex', 'operations': ['read_write']}, {'path': '/cartridges', 'operations': ['read_write']}, {'path': '/static', 'operations': ['read_write']}]
```

### CloneState {#clonestate}

```python
CloneState = str
```

### SandboxState {#sandboxstate}

```python
SandboxState = str
```
