client.system_tenants
client.system_tenants — the systemTenants operations.
On AsyncKindgi every method is the same, awaited.
client.system_tenants.list()
Section titled “client.system_tenants.list()”list( *, limit: int | None = None, cursor: str | None = None, timeout: float | None = None,) -> SystemTenantListList tenants. GET /v1/system/tenants
Newest first; purged tenants are left out. Takes system:tenants. Never a tenant's content.
client.system_tenants.create()
Section titled “client.system_tenants.create()”create( body: CreateSystemTenantBody | Mapping[str, Any] | None = None, /, *, idempotency_key: str | None = None, timeout: float | None = None, **fields: Any,) -> CreateSystemTenantResultCreate 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()
Section titled “client.system_tenants.get()”get(tenant_id: str | UUID, /, *, timeout: float | None = None) -> SystemTenantRead a tenant. GET /v1/system/tenants/{tenantId}
Its state, switch, image prefix and dates. Takes system:tenants.
client.system_tenants.close()
Section titled “client.system_tenants.close()”close( tenant_id: str | UUID, /, *, idempotency_key: str | None = None, timeout: float | None = None,) -> SystemTenantClose 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()
Section titled “client.system_tenants.set_suspended()”set_suspended( tenant_id: str | UUID, body: SetTenantSuspendedBody | Mapping[str, Any] | None = None, /, *, idempotency_key: str | None = None, timeout: float | None = None, **fields: Any,) -> SystemTenantSuspend 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()
Section titled “client.system_tenants.set_image_prefix()”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,) -> SystemTenantSet 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()
Section titled “client.system_tenants.set_project_suspended()”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,) -> ProjectSuspensionSuspend 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()
Section titled “client.system_tenants.admins()”admins(tenant_id: str | UUID, /, *, timeout: float | None = None) -> TenantAdminContactsA 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.set_production_allowed()
Section titled “client.system_tenants.set_production_allowed()”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,) -> TenantProductionAllowedAllow 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()
Section titled “client.system_tenants.limits()”limits(tenant_id: str | UUID, /, *, timeout: float | None = None) -> TenantLimitsResultRead 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()
Section titled “client.system_tenants.set_limits()”set_limits( tenant_id: str | UUID, body: TenantLimits | Mapping[str, Any] | None = None, /, *, idempotency_key: str | None = None, timeout: float | None = None, **fields: Any,) -> TenantLimitsResultSet 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.