---
title: Organizations and workspaces
description: Organizations and workspaces in the dltHub Runtime Python SDK (dlthub_sdk)
keywords: [dlthub, runtime, python sdk, dlthub_sdk, api]
---
# Organizations and workspaces

<!-- generated from dlthub-client 0.28.8a3, do not edit -->

New to the SDK? [Getting started](getting-started.md) shows how to connect and use it.

## Organizations

### `Organizations` {#organizations}

The organizations the caller belongs to.

#### `Organizations.get()` {#organizations-get}

```python
get(*, id: str) -> Organization
```

Return one organization by id.

**Arguments**

| Name | Type | Description |
| --- | --- | --- |
| `id` | <code>str</code> | The organization uuid. |

**Returns:** <code><a href="#organization">Organization</a></code> — The organization; awaitable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| [`BadRequest`](errors.md#badrequest) | The request was rejected as invalid; `message`, `code` and `fields` say why. |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| [`NotFound`](errors.md#notfound) | No such organization. |

#### `Organizations.count()` {#organizations-count}

```python
count() -> int
```

Return how many organizations the caller belongs to.

**Returns:** <code>int</code> — The organization count; awaitable in async mode. Saturates at 10,001.

#### `Organizations.list()` {#organizations-list}

```python
list(
    *,
    limit: int | None = None,
    offset: int = 0,
) -> Iterable[Organization] | AsyncIterable[Organization]
```

Yield the organizations the caller belongs to, paging lazily.

Needs no scope, so this is the entry point when the caller knows no ids
yet.

**Arguments**

| Name | Type | Description |
| --- | --- | --- |
| `limit` | <code>int &#124; None</code> | Return at most this many. `None` walks to the end, or to row 10,100, past which the platform does not page. |
| `offset` | <code>int</code> | Skip this many, server-side. |

**Returns:** <code>Iterable[<a href="#organization">Organization</a>] &#124; AsyncIterable[<a href="#organization">Organization</a>]</code> — An iterable of organizations; async-iterable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| `ValueError` | A negative `limit` or `offset`. |

### `Organization` {#organization}

An organization: what workspaces, members and billing hang off.

**[Collections](getting-started.md#collections-and-attributes)**

| Name | Type | Example | Description |
| --- | --- | --- | --- |
| `organization.workspaces` | <code><a href="#workspaces">Workspaces</a></code> | `organization.workspaces.list()` | The workspaces in this organization. |

**Attributes**

| Name | Type | Description |
| --- | --- | --- |
| `id` | <code>str</code> | Unique ID (a UUID). |
| `name` | <code>str</code> | The name of the organization. |
| `description` | <code>str &#124; None</code> | Free-text description of the organization; `None` when none is set. |
| `dataplane_id` | <code>str &#124; None</code> | Data plane of the organization's workspaces; `None` until a region is set. |
| `created_at` | <code>datetime</code> | When it was created. |

#### `Organization.set_dataplane()` {#organization-set_dataplane}

```python
set_dataplane(*, dataplane_id: str) -> Organization
```

Choose the data plane this organization's workspaces live on.

Must be set before the organization can hold any workspace, and it
fixes where that data resides. One-time and irreversible.

**Arguments**

| Name | Type | Description |
| --- | --- | --- |
| `dataplane_id` | <code>str</code> | The data plane to assign. |

**Returns:** <code><a href="#organization">Organization</a></code> — A fresh snapshot; awaitable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| [`BadRequest`](errors.md#badrequest) | The request was rejected as invalid; `message`, `code` and `fields` say why. |
| [`Conflict`](errors.md#conflict) | The current state does not allow the call, e.g. the workspace is archived; `code` and `message` say why. |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| [`NotFound`](errors.md#notfound) | The organization does not exist. |

#### `Organization.me()` {#organization-me}

```python
me() -> OrganizationCaller
```

Who the caller is here, what they may do, and where they belong.

One call, and it answers for an API key as well as a user token.

**Returns:** <code><a href="#organizationcaller">OrganizationCaller</a></code> — The caller's identity, role, and workspace memberships in this organization; awaitable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| [`NotFound`](errors.md#notfound) | The organization no longer exists. |

### `Membership` {#membership}

A workspace the caller belongs to, and their role in it.

**Attributes**

| Name | Type | Description |
| --- | --- | --- |
| `workspace` | <code><a href="#workspace">Workspace</a></code> | The workspace, bound and ready to navigate from. |
| `role` | <code>str</code> | The role of the user in the workspace. |

### `OrganizationCaller` {#organizationcaller}

Who the token belongs to, and what they may do in one organization.

**Attributes**

| Name | Type | Description |
| --- | --- | --- |
| `email` | <code>str</code> | The email of the current user. |
| `user_id` | <code>str</code> | The ID of the current user. |
| `organization_membership_id` | <code>str</code> | The ID of the organization member for this organization. |
| `role` | <code>str</code> | The role of the user in this organization. |
| `workspace_memberships` | <code>tuple[<a href="#membership">Membership</a>, ...]</code> | The organization's workspaces the caller belongs to. |

## Workspaces

### `Workspaces` {#workspaces}

Workspace lookup, scoped by the context it is reached through.

#### `Workspaces.create()` {#workspaces-create}

```python
create(
    *,
    name: str,
    description: str | None = None,
    organization_id: str | None = None,
) -> Workspace
```

Create a workspace in an organization.

**Arguments**

| Name | Type | Description |
| --- | --- | --- |
| `name` | <code>str</code> | Name for the new workspace. Names need not be unique. |
| `description` | <code>str &#124; None</code> | Free-text description, or `None` for none. |
| `organization_id` | <code>str &#124; None</code> | Overrides the organization in scope. Required when the context carries none. |

**Returns:** <code><a href="#workspace">Workspace</a></code> — The new workspace, scoped so its jobs are reachable; awaitable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| [`BadRequest`](errors.md#badrequest) | The request was rejected as invalid; `message`, `code` and `fields` say why. |
| [`Conflict`](errors.md#conflict) | The current state does not allow the call, e.g. the workspace is archived; `code` and `message` say why. |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| [`NotFound`](errors.md#notfound) | No such organization. |
| [`ScopeMissing`](errors.md#scopemissing) | No organization in scope and none passed. |

#### `Workspaces.get()` {#workspaces-get}

```python
get(*, id: str) -> Workspace
```

Return one workspace by id.

**Arguments**

| Name | Type | Description |
| --- | --- | --- |
| `id` | <code>str</code> | The workspace uuid. |

**Returns:** <code><a href="#workspace">Workspace</a></code> — The workspace; awaitable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| [`BadRequest`](errors.md#badrequest) | The request was rejected as invalid; `message`, `code` and `fields` say why. |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| [`NotFound`](errors.md#notfound) | No such workspace. |

#### `Workspaces.count()` {#workspaces-count}

```python
count(*, organization_id: str | None = None) -> int
```

Count the workspaces of one organization, without fetching them.

Counts the live (unarchived) workspaces of the organization that the
caller can see.

**Arguments**

| Name | Type | Description |
| --- | --- | --- |
| `organization_id` | <code>str &#124; None</code> | Overrides the organization in scope. Required when the context carries none. |

**Returns:** <code>int</code> — The workspace count; awaitable in async mode. Saturates at 10,001.

**Raises**

| Exception | When |
| --- | --- |
| [`BadRequest`](errors.md#badrequest) | The request was rejected as invalid; `message`, `code` and `fields` say why. |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| [`NotFound`](errors.md#notfound) | No such organization. |
| [`ScopeMissing`](errors.md#scopemissing) | No organization in scope and none passed. |

#### `Workspaces.list()` {#workspaces-list}

```python
list(
    *,
    organization_id: str | None = None,
    limit: int | None = None,
    offset: int = 0,
) -> Iterable[Workspace] | AsyncIterable[Workspace]
```

Yield the workspaces of one organization, paging lazily.

Yields the live (unarchived) workspaces of the organization that the
caller can see. Errors from the platform are raised when iteration
begins.

**Arguments**

| Name | Type | Description |
| --- | --- | --- |
| `organization_id` | <code>str &#124; None</code> | Overrides the organization in scope. Required when the context carries none. |
| `limit` | <code>int &#124; None</code> | Return at most this many workspaces. `None` walks to the end, or to row 10,100, past which the platform does not page. |
| `offset` | <code>int</code> | Skip this many workspaces, server-side. |

**Returns:** <code>Iterable[<a href="#workspace">Workspace</a>] &#124; AsyncIterable[<a href="#workspace">Workspace</a>]</code> — An iterable of workspaces; async-iterable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| [`BadRequest`](errors.md#badrequest) | The request was rejected as invalid; `message`, `code` and `fields` say why. |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| [`NotFound`](errors.md#notfound) | No such organization. |
| [`ScopeMissing`](errors.md#scopemissing) | No organization in scope and none passed. |
| `ValueError` | A negative `limit` or `offset`. |

### `Workspace` {#workspace}

A workspace: the unit a job is deployed into.

**[Collections](getting-started.md#collections-and-attributes)**

| Name | Type | Example | Description |
| --- | --- | --- | --- |
| `workspace.job_runs` | <code><a href="job-runs#jobruns">JobRuns</a></code> | `workspace.job_runs.list()` | The job runs of this workspace, across all its jobs. |
| `workspace.deployments` | <code><a href="deployments#deployments">Deployments</a></code> | `workspace.deployments.list()` | The versions of code this workspace has been given. |
| `workspace.configurations` | <code><a href="deployments#configurations">Configurations</a></code> | `workspace.configurations.list()` | The versions of configuration this workspace has been given. |
| `workspace.telemetry` | <code><a href="telemetry#telemetry">Telemetry</a></code> | `workspace.telemetry.status()` | What the platform observed of the pipelines this workspace ran. |
| `workspace.variables` | <code><a href="variables#variables">Variables</a></code> | `workspace.variables.list()` | The variables this workspace's job runs read. |
| `workspace.jobs` | <code><a href="jobs#jobs">Jobs</a></code> | `workspace.jobs.list()` | The jobs deployed in this workspace. |

**Attributes**

| Name | Type | Description |
| --- | --- | --- |
| `id` | <code>str</code> | Unique ID (a UUID). |
| `name` | <code>str</code> | The name of the workspace. |
| `description` | <code>str &#124; None</code> | Free-text description of the workspace; `None` when none is set. |
| `organization_id` | <code>str</code> | The ID of the parent organization. |
| `dataplane_id` | <code>str</code> | Identifier of the data plane that holds this workspace's user data. Matches the subdomain of the plane's public entrypoint. |
| `is_playground` | <code>bool</code> | Whether this is the user's auto-created personal playground workspace. A playground has a single member and cannot be updated, archived, shared, or given API keys. |
| `predefined_profiles` | <code>Mapping[str, str]</code> | Profile names the platform offers for this workspace, keyed by access level. Empty when it declares none. |
| `created_at` | <code>datetime</code> | When it was created. |
| `archived_at` | <code>datetime &#124; None</code> | When the workspace was archived; `None` when live. An archived workspace rejects all changes except unarchiving, though owners can still manage its workspace variables. |
| `dashboard_url` | <code>str</code> | Where this workspace's dashboard lives in the web UI. |

#### `Workspace.update()` {#workspace-update}

```python
update(*, name: str | Keep = KEEP, description: str | None | Keep = KEEP) -> Workspace
```

Change the workspace's name, its description, or both.

**Arguments**

| Name | Type | Description |
| --- | --- | --- |
| `name` | <code>str &#124; <a href="client#keep">Keep</a></code> | New name. Omit to leave it unchanged. |
| `description` | <code>str &#124; None &#124; <a href="client#keep">Keep</a></code> | New description. Pass `None` to clear it, omit to leave it unchanged. |

**Returns:** <code><a href="#workspace">Workspace</a></code> — A fresh snapshot; awaitable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| [`BadRequest`](errors.md#badrequest) | The request was rejected as invalid; `message`, `code` and `fields` say why. |
| [`Conflict`](errors.md#conflict) | The current state does not allow the call, e.g. the workspace is archived; `code` and `message` say why. |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| [`NotFound`](errors.md#notfound) | The workspace no longer exists. |

#### `Workspace.archive()` {#workspace-archive}

```python
archive() -> Workspace
```

Freeze the workspace: its schedules stop and it refuses changes.

**Returns:** <code><a href="#workspace">Workspace</a></code> — A fresh snapshot with `archived_at` set; awaitable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| [`BadRequest`](errors.md#badrequest) | The request was rejected as invalid; `message`, `code` and `fields` say why. |
| [`Conflict`](errors.md#conflict) | The current state does not allow the call, e.g. the workspace is archived; `code` and `message` say why. |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| [`NotFound`](errors.md#notfound) | The workspace no longer exists. |

#### `Workspace.unarchive()` {#workspace-unarchive}

```python
unarchive() -> Workspace
```

Reopen an archived workspace and restart its schedules.

**Returns:** <code><a href="#workspace">Workspace</a></code> — A fresh snapshot with `archived_at` cleared; awaitable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| [`Conflict`](errors.md#conflict) | The current state does not allow the call, e.g. the workspace is archived; `code` and `message` say why. |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| [`NotFound`](errors.md#notfound) | The workspace no longer exists. |

#### `Workspace.members()` {#workspace-members}

```python
members(
    *,
    limit: int | None = None,
    offset: int = 0,
) -> Iterable[WorkspaceMember] | AsyncIterable[WorkspaceMember]
```

Who has access to this workspace, and in what role.

**Arguments**

| Name | Type | Description |
| --- | --- | --- |
| `limit` | <code>int &#124; None</code> | Return at most this many. `None` walks to the end, or to row 10,100, past which the platform does not page. |
| `offset` | <code>int</code> | Skip this many, server-side. |

**Returns:** <code>Iterable[<a href="#workspacemember">WorkspaceMember</a>] &#124; AsyncIterable[<a href="#workspacemember">WorkspaceMember</a>]</code> — An iterable of members; async-iterable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| `ValueError` | A negative `limit` or `offset`. |

#### `Workspace.me()` {#workspace-me}

```python
me() -> WorkspaceCaller
```

Who the caller is here, and what they may do.

One call, and it answers for an API key as well as a user token. Also
records this workspace as the caller's most recent one, so
[`Runtime.me()`](client.md#runtime-me) then reports its organization as `latest_organization`.

**Returns:** <code><a href="#workspacecaller">WorkspaceCaller</a></code> — The caller's identity and roles; awaitable in async mode.

**Raises**

| Exception | When |
| --- | --- |
| [`NotAuthorized`](errors.md#notauthorized) | The caller lacks the access this call needs; `message` says why. |
| [`NotFound`](errors.md#notfound) | The workspace no longer exists. |

### `WorkspaceCaller` {#workspacecaller}

Who the token belongs to, and what they may do in one workspace.

**Attributes**

| Name | Type | Description |
| --- | --- | --- |
| `email` | <code>str</code> | The email of the current user. |
| `user_id` | <code>str</code> | The ID of the current user. |
| `organization_membership_id` | <code>str</code> | The ID of the organization member in the parent organization. |
| `organization_id` | <code>str</code> | Unique ID (a UUID). |
| `organization_role` | <code>str</code> | The role of the user in the parent organization. |
| `workspace_role` | <code>str</code> | The role of the user in this workspace. |

### `WorkspaceMember` {#workspacemember}

One member of a workspace: a person or a service account (workspace API key).

**Attributes**

| Name | Type | Description |
| --- | --- | --- |
| `email` | <code>str</code> | The email of the user. |
| `user_id` | <code>str</code> | The ID of the user. |
| `role` | <code>str</code> | The role of the user in the workspace. |
| `name` | <code>str &#124; None</code> | Display name; `None` when the user has no name set. |

## Caller

### `Caller` {#caller}

The person the token belongs to.

Returned for a user token or a user API key; a service-account API key gets
`dlthub_sdk.NotAuthorized` instead (see `dlthub_sdk.Runtime.me()`).
[`Organization.me()`](#organization-me) and [`Workspace.me()`](#workspace-me) answer for any caller.

**Attributes**

| Name | Type | Description |
| --- | --- | --- |
| `email` | <code>str</code> | The email of the current user. |
| `user_id` | <code>str</code> | The ID of the current user. |
| `organization_membership_id` | <code>str</code> | Your membership id in `latest_organization`. |
| `name` | <code>str &#124; None</code> | The user's display name (full name); `None` if the identity provider supplied none. |
| `primary_organization` | <code><a href="#organization">Organization</a></code> | The organization where new workspaces are created by default. |
| `latest_organization` | <code><a href="#organization">Organization</a></code> | The organization you used most recently. |
| `organization_memberships` | <code>tuple[<a href="#organizationmembership">OrganizationMembership</a>, ...]</code> | Every organization they belong to. |

### `OrganizationMembership` {#organizationmembership}

An organization the caller belongs to, and their role in it.

**Attributes**

| Name | Type | Description |
| --- | --- | --- |
| `organization` | <code><a href="#organization">Organization</a></code> | The organization, bound and ready to navigate from. |
| `role` | <code>str</code> | The role of the user in the organization. |
| `is_active` | <code>bool</code> | Whether the membership is active. |

## Data planes

### `Dataplanes` {#dataplanes}

The data planes this caller may choose from.

They arrive in one answer, so there is nothing to page and no count to ask
for.

#### `Dataplanes.list()` {#dataplanes-list}

```python
list() -> tuple[Dataplane, ...]
```

Return every data plane available to this caller.

Needs no scope, like [`Organizations.list()`](#organizations-list).

**Returns:** <code>tuple[<a href="#dataplane">Dataplane</a>, ...]</code> — All of them, in the platform's order; awaitable in async mode.

### `Dataplane` {#dataplane}

A data plane an organization can put its workspaces on.

**Attributes**

| Name | Type | Description |
| --- | --- | --- |
| `id` | <code>str</code> | Data plane id, e.g. `eu1`; also the subdomain of its URL. |
| `name` | <code>str</code> | Human-readable data plane name. |
| `region` | <code>str</code> | Cloud region the data plane runs in, e.g. `europe-west4`. |
| `description` | <code>str &#124; None</code> | Optional note about the data plane; `None` when there is none. |
