# client.system_tenants

> client.system_tenants — the systemTenants operations.

`client.system_tenants` — the `systemTenants` operations.

On `AsyncKindgi` every method is the same, awaited.

## `client.system_tenants.list()`

```python signature
list(
    *,
    limit: int | None = None,
    cursor: str | None = None,
    timeout: float | None = None,
) -> SystemTenantList
```

List tenants. `GET /v1/system/tenants`

Newest first; purged tenants are left out. Takes `system:tenants`. Never a tenant's content.

## `client.system_tenants.create()`

```python signature
create(
    body: CreateSystemTenantBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> CreateSystemTenantResult
```

Create a tenant. `POST /v1/system/tenants`

Creates a tenant on a runtime serving many tenants, with its setup (its default project, its authorization store). Safe to retry with the same slug: if the setup didn't finish, the tenant waits, frozen, and the same request (the same name, slug, settings and first admin, under any Idempotency-Key) finishes it and answers as the first would have; another request naming that slug is `tenant-slug-taken`. A repeat of a create that finished is `tenant-slug-taken` too, unless it carries the first request's Idempotency-Key: then it gets the first answer again, or `409 idempotency-key-replay-withheld` when that answer held the admin key, which is never sent twice (send an Idempotency-Key with every create, so a lost answer can be told from another tenant's slug). With `firstAdmin`, that person becomes its admin and member by email, with every capability but `secrets:reveal`, and the runtime's own sign-in finds them; the answer carries no key. Without it, the answer carries the tenant's first admin key, shown once, and that takes the full system capability (`kindgi:system`), as does a `test` tenant. Takes `system:tenants:create` (sign-up's) or `system:tenants`. A tenant created here starts with production blocked; `productionAllowed: true` takes `system:tenants:production`, and `imagePrefix` takes `system:tenants:image-prefix`. Asking for more than the key's scopes is refused naming the scope, never dropped. An Idempotency-Key retry answers the same tenant, with the admin key withheld.

## `client.system_tenants.get()`

```python signature
get(tenant_id: str | UUID, /, *, timeout: float | None = None) -> SystemTenant
```

Read a tenant. `GET /v1/system/tenants/{tenantId}`

Its state, switch, image prefix and dates. Takes `system:tenants`.

## `client.system_tenants.update()`

```python signature
update(
    tenant_id: str | UUID,
    body: TenantPatch | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> None
```

Rename a tenant. `PATCH /v1/system/tenants/{tenantId}`

Changes its name, its slug, or both, as the tenant's own admins can (`PATCH /v1/tenant`); a field left out stays as it is. Its id stays. The same values again change nothing. Takes `system:tenants`. A closing tenant is refused (`409 tenant-closing`). A runtime whose tenant-hierarchy binding can't rename tenants doesn't serve this route.

## `client.system_tenants.close()`

```python signature
close(
    tenant_id: str | UUID,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
) -> SystemTenant
```

Close a tenant. `POST /v1/system/tenants/{tenantId}/close`

Starts the end of its contract: the tenant becomes `closing`. Its own keys and sessions still read and export it for its window; nothing runs (its running runs are cancelled), and nothing is written but deletes. One-way: the purge follows the window. A second close keeps the first. Takes `system:tenants`.

## `client.system_tenants.set_suspended()`

```python signature
set_suspended(
    tenant_id: str | UUID,
    body: SetTenantSuspendedBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> SystemTenant
```

Suspend a tenant, or restore it. `PUT /v1/system/tenants/{tenantId}/suspended`

Reversible: a suspended tenant's own keys and sessions still read and export it; nothing runs (its running runs are cancelled), and nothing is written but deletes. Its schedules and triggers are skipped, not changed, so restoring resumes exactly what was on. Nothing that came due meanwhile runs late: at the restore, a fire whose run or pass hadn't started is recorded `skipped` (`tenant-suspended`), and a schedule that's on fires next at its first occurrence after the restore, whatever its `catchUp`. A second suspend keeps the first one's time and reason; restoring clears both. Takes `system:suspend`, which no other scope includes. A closing tenant is refused (`409 tenant-closing`).

## `client.system_tenants.set_image_prefix()`

```python signature
set_image_prefix(
    tenant_id: str | UUID,
    body: SetTenantImagePrefixBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> SystemTenant
```

Set the repository a tenant's images must sit in. `PUT /v1/system/tenants/{tenantId}/image-prefix`

Each tenant may deploy only images at or under its own repository: `<host>/<path>`, matched on a path boundary, with no trailing slash. On a runtime serving many tenants, a tenant without one can't register a deployment. Takes `system:tenants:image-prefix`, the key that binds the tenant's slot; changing a prefix that's already set takes the full system capability. A closing tenant is refused (`409 tenant-closing`).

## `client.system_tenants.set_project_suspended()`

```python signature
set_project_suspended(
    tenant_id: str | UUID,
    project_id: str | UUID,
    body: SetTenantSuspendedBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> ProjectSuspension
```

Suspend one of a tenant's projects, or restore it. `PUT /v1/system/tenants/{tenantId}/projects/{projectId}/suspended`

Reversible: nothing new runs or deploys in the project, its running runs are cancelled and its deployments retired; reads and the rest of the tenant are untouched. Its schedules' fires are recorded `skipped` (`project-suspended`) and don't count toward the auto-pause, so a schedule stays on and fires again once the project is restored. A delivery to one of its webhook triggers is answered `skipped: project-suspended`, and nothing is recorded. A second suspend keeps the first one's time and reason; restoring clears both. Takes `system:suspend`. A closing tenant is refused (`409 tenant-closing`).

## `client.system_tenants.admins()`

```python signature
admins(tenant_id: str | UUID, /, *, timeout: float | None = None) -> TenantAdminContacts
```

A tenant's admins' contact addresses. `GET /v1/system/tenants/{tenantId}/admins`

For the operator's service notices (a breach, maintenance, a new sub-processor, a terms change): the tenant's active admins with a primary email, at most 100, and only their id, email and display name. Account contacts, never the tenant's content. Takes its own scope, `system:tenants:contacts`, and every read is recorded.

## `client.system_tenants.purge()`

```python signature
purge(
    tenant_id: str | UUID,
    body: PurgeTenantBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> SystemTenantPurge
```

Purge a closed tenant, for good. `POST /v1/system/tenants/{tenantId}/purge`

Deletes a `closing` tenant whose 30-day export window has passed: every row of it, its artifacts' bytes and its authorization store. Once nothing of it is left, its purge record is written, so a restore from an older backup purges it again, and it's marked purged: its tenants row stays, and nothing of it signs in or is served. Then, once each server has seen the mark, it deletes again what work under way at the mark wrote meanwhile. Irreversible. `confirm` is the tenant's slug, a second check on the id. It answers when done. Safe to run again: a run that stopped part-way (`complete: false`, or a request that ended before its answer) is finished by the next, and on a tenant already purged it deletes what was written after its mark, leaving its mark and its record as they were. A run again is a new request: a new Idempotency-Key, or none. Takes its own scope, `system:tenants:purge`, which no other scope includes, or `kindgi:system`.

## `client.system_tenants.set_production_allowed()`

```python signature
set_production_allowed(
    tenant_id: str | UUID,
    body: ProductionAllowedBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> TenantProductionAllowed
```

Allow a tenant production, or stop it. `PUT /v1/system/tenants/{tenantId}/production-allowed`

The switch the production gate reads: with it off, `PUT /v1/projects/{projectId}/production` refuses to put the tenant's projects in production (`403 production-not-allowed`), and projects already in production stay so. A tenant made by `POST /v1/system/tenants` starts with it off, unless the create says `productionAllowed: true`; the tenant a server makes for itself, and one from before the switch, start with it on. Takes `system:tenants:production`. A closing tenant is frozen: `409 tenant-closing`.

## `client.system_tenants.limits()`

```python signature
limits(tenant_id: str | UUID, /, *, timeout: float | None = None) -> TenantLimitsResult
```

Read a tenant's limits. `GET /v1/system/tenants/{tenantId}/limits`

The tenant's limits as stored, in the shape `PUT` takes: to change one, read them, change it and put them all back. A limit that isn't set is absent, and isn't enforced. From a runtime that counts it, `inUse` says how much of each counted limit the tenant uses now (`projectsInProduction`), which can be over a limit lowered below it. Takes `system:tenants:limits`. A closing tenant's limits can be read.

## `client.system_tenants.set_limits()`

```python signature
set_limits(
    tenant_id: str | UUID,
    body: TenantLimits | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> TenantLimitsResult
```

Set a tenant's limits. `PUT /v1/system/tenants/{tenantId}/limits`

Replaces the tenant's limits with exactly these: a limit left out isn't set, and isn't enforced. Each is a whole number from 1 to 1000000. The tenant reads them on `GET /v1/tenant`. Takes `system:tenants:limits`. A closing tenant is frozen: `409 tenant-closing`.
