Tenant endpoints
Endpoints for tenant lifecycle and tenant-admin membership.
| Endpoint | Auth | Status |
|---|---|---|
POST /api/v1/tenants | superadmin | v0 |
GET /api/v1/tenants | authenticated principal | v0 |
GET /api/v1/tenants/{tenant} | tenant member or higher | v0 |
PUT /api/v1/tenants/{tenant}/admins/{user_id} | tenant admin | deferred |
DELETE /api/v1/tenants/{tenant}/admins/{user_id} | tenant admin | deferred |
See conventions for the auth header, error envelope, pagination, and rate limits — every endpoint here inherits them.
POST /api/v1/tenants
Create a new tenant. An exd installation can contain multiple tenants. Each tenant maps to either a configured SSO provider or a verified email domain.
Auth required: superadmin. See access-control — tenant.create.
Request body (SSO tenant)
{
"slug": "acme",
"display_name": "Acme Corp",
"login_mode": "sso",
"sso_provider": "acme-oidc",
"initial_admin_user_ids": ["usr_01HV5Z9R4Y0XJ7A2W8WJ9R7S3A"]
}
Request body (email-domain tenant)
{
"slug": "acme",
"display_name": "Acme Corp",
"login_mode": "email_domain",
"email_domain": "acme.example"
}
Fields
| Field | Type | Required | Description |
|---|---|---|---|
slug | string | yes | Tenant slug. Pattern [a-z][a-z0-9-]*, max 63 chars. Globally unique across the installation. Immutable. |
display_name | string | no | Human-readable name. Defaults to the slug. |
login_mode | string | yes | sso or email_domain. |
sso_provider | string | when login_mode = "sso" | Identifier for a configured OIDC or SAML provider. |
email_domain | string | when login_mode = "email_domain" | Verified domain used to admit email-login users. |
initial_admin_user_ids | array | no | Initial tenant admins for SSO tenants. Ignored for email-domain tenants (every admitted user is a tenant admin). |
Response: 201 Created
{
"tenant": {
"slug": "acme",
"display_name": "Acme Corp",
"login_mode": "sso",
"sso_provider": "acme-oidc",
"email_domain": null,
"created_at": "2026-04-25T09:00:00Z",
"namespace_count": 0
},
"request_id": "01HV5XK1EFQT8N3JRDCP7MW04A"
}
GET /api/v1/tenants
List tenants visible to the authenticated principal.
Auth required: authenticated user, tenant-admin, or superadmin. List endpoints filter to the principal's visible scope.
Query parameters
Supports limit + after (pagination).
Response: 200 OK
{
"tenants": [
{
"slug": "acme",
"display_name": "Acme Corp",
"login_mode": "sso",
"sso_provider": "acme-oidc",
"email_domain": null,
"created_at": "2026-04-25T09:00:00Z",
"namespace_count": 2,
"current_user_roles": ["tenant_admin"]
}
],
"next_cursor": null,
"request_id": "01HV5XK2EFQT8N3JRDCP7MW04B"
}
GET /api/v1/tenants/{tenant}
Retrieve metadata for a single tenant.
Auth required: tenant member, tenant-admin bound to this tenant, or superadmin. Permission: tenant.read.
Response: 200 OK
Same tenant object as the create response, plus the requester's roles.
PUT /api/v1/tenants/{tenant}/admins/{user_id}
Deferred. Not implemented in v0.
Grant tenant-admin access to a user. Valid for SSO tenants. Email-domain tenants do NOT need explicit tenant-admin grants — every verified user in the tenant is a tenant admin.
Auth required: tenant_admin for this tenant or superadmin. Permission: tenant.admin.manage.
DELETE /api/v1/tenants/{tenant}/admins/{user_id}
Deferred. Not implemented in v0.
Revoke explicit tenant-admin access from a user in an SSO tenant.
Auth required: tenant_admin for this tenant or superadmin. Permission: tenant.admin.manage.
See also
- namespaces — flag namespaces are scoped under tenants.
- access-control § Tenant admin — what
tenant_admincan do. exd-server-admin tenant create— operator CLI alternative.