> For the complete documentation index, see [llms.txt](https://docs.toolkit.equs.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.toolkit.equs.ai/api/identity-manager-api/tenants.md).

# Tenants

## Register a tenant for an operator

> Creates the tenant in the Control API, then an organization in Keycloak,then in identity-pool if enabled.&#x20;

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"sp":[]}],"components":{"securitySchemes":{"sp":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Service Provider. Token of the Service Provider client in the `agents` realm, with no `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"CreateTenantRequest":{"type":"object","properties":{"name":{"type":"string","description":"Display name of the tenant. Its slug is derived from this name and is the registration key, so the name is restricted to letters, digits, spaces and hyphens, and must start with a letter or digit."},"email":{"type":"string","description":"Email address of this tenant organization. Used to send notifications about updates in embed UI origin status."},"environment":{"type":"string","description":"Environment the tenant operates in. Defaults to production; sandbox tenants are for evaluation and testing.","enum":["sandbox","production"]},"accessExpiresAt":{"type":"object","description":"Tenant expiration date, which must be in the future. Omit to default to 90 days from now (configurable per deployment); send null so its access never expires. Change it later with PUT /tenants/{id}/access-expiry.","nullable":true},"maxIssuers":{"type":"number","description":"Maximum number of Issuers the tenant may own."},"maxVerifiers":{"type":"number","description":"Maximum number of Verifiers the tenant may own."},"brandingMetadata":{"description":"Tenant branding metadata used to customize Embedded UI components.","allOf":[{"$ref":"#/components/schemas/TenantBrandingMetadata"}]}},"required":["name","email"]},"TenantBrandingMetadata":{"type":"object","properties":{"primaryColor":{"type":"string","maxLength":64,"description":"Primary brand color used for CTAs and key UI elements."},"primaryColorHover":{"type":"string","maxLength":64,"description":"Primary brand color applied on hover state."},"primaryColorPressed":{"type":"string","maxLength":64,"description":"Primary brand color applied on pressed/active state."},"primaryOpacity08":{"type":"string","maxLength":64,"description":"Primary brand color at 8% opacity, used for subtle backgrounds."},"primaryOpacity16":{"type":"string","maxLength":64,"description":"Primary brand color at 16% opacity, used for subtle backgrounds."},"primaryOpacity20":{"type":"string","maxLength":64,"description":"Primary brand color at 20% opacity, used for subtle backgrounds."},"primaryDisabled":{"type":"string","maxLength":64,"description":"Primary brand color applied to disabled UI elements."},"darkOpacity05":{"type":"string","maxLength":64,"description":"Dark overlay color at 5% opacity."},"darkOpacity08":{"type":"string","maxLength":64,"description":"Dark overlay color at 8% opacity."},"darkOpacity12":{"type":"string","maxLength":64,"description":"Dark overlay color at 12% opacity."},"darkDivider":{"type":"string","maxLength":64,"description":"Dark color used for borders and dividers."},"darkOutlineMedium":{"type":"string","maxLength":64,"description":"Dark medium-emphasis color used for outlines."},"darkOutlineHigh":{"type":"string","maxLength":64,"description":"Dark high-emphasis color used for outlines."},"onSurfaceDarkHighEmphasis":{"type":"string","maxLength":64,"description":"Dark high-emphasis text/icon color rendered on light surfaces."},"onSurfaceDarkMediumEmphasis":{"type":"string","maxLength":64,"description":"Dark medium-emphasis text/icon color rendered on light surfaces."},"onSurfaceDarkDisabled":{"type":"string","maxLength":64,"description":"Dark disabled text/icon color rendered on light surfaces."},"onSurfaceLightHighEmphasis":{"type":"string","maxLength":64,"description":"Light high-emphasis text/icon color rendered on dark surfaces."},"onSurfaceLightMediumEmphasis":{"type":"string","maxLength":64,"description":"Light medium-emphasis text/icon color rendered on dark surfaces."},"onSurfaceLightDisabled":{"type":"string","maxLength":64,"description":"Light disabled text/icon color rendered on dark surfaces."},"textOnSurface":{"type":"string","maxLength":64,"description":"Default text color rendered on top of a surface background."},"surfaceNull":{"type":"string","maxLength":64,"description":"Base surface color with no elevation applied."},"cardBg":{"type":"string","maxLength":64,"description":"Background color used for card components."},"cardStroke":{"type":"string","maxLength":64,"description":"Border/stroke color used around card components."},"surface1":{"type":"string","maxLength":64,"description":"Elevation level 1 surface color."},"surface2":{"type":"string","maxLength":64,"description":"Elevation level 2 surface color."},"surface3":{"type":"string","maxLength":64,"description":"Elevation level 3 surface color."},"surface4":{"type":"string","maxLength":64,"description":"Elevation level 4 surface color."},"surface5":{"type":"string","maxLength":64,"description":"Elevation level 5 surface color."},"surfaceGrey1":{"type":"string","maxLength":64,"description":"Grey surface tone, level 1."},"surfaceGrey2":{"type":"string","maxLength":64,"description":"Grey surface tone, level 2."},"surfaceGrey3":{"type":"string","maxLength":64,"description":"Grey surface tone, level 3."},"surfaceGrey4":{"type":"string","maxLength":64,"description":"Grey surface tone, level 4."},"surfaceGrey5":{"type":"string","maxLength":64,"description":"Grey surface tone, level 5."},"shutterDark70":{"type":"string","maxLength":64,"description":"Dark modal/overlay shutter color at 70% opacity."},"shutterDark30":{"type":"string","maxLength":64,"description":"Dark modal/overlay shutter color at 30% opacity."},"shutterLight32":{"type":"string","maxLength":64,"description":"Light modal/overlay shutter color at 32% opacity."},"shutterLight75":{"type":"string","maxLength":64,"description":"Light modal/overlay shutter color at 75% opacity."},"linkColor":{"type":"string","maxLength":64,"description":"Color applied to hyperlinks."},"widgetColor":{"type":"string","maxLength":64,"description":"Base color used for embedded widget backgrounds."},"widgetColorHover":{"type":"string","maxLength":64,"description":"Embedded widget accent color applied on hover state."},"widgetColorPressed":{"type":"string","maxLength":64,"description":"Embedded widget accent color applied on pressed state."},"notificationColor":{"type":"string","maxLength":64,"description":"Base color used to indicate error states."},"notificationHover":{"type":"string","maxLength":64,"description":"Notification color applied on hover state."},"notificationPressed":{"type":"string","maxLength":64,"description":"Notification color applied on pressed state."},"notificationOpacity08":{"type":"string","maxLength":64,"description":"Notification color at 8% opacity, used for subtle backgrounds."},"notificationOpacity12":{"type":"string","maxLength":64,"description":"Notification color at 12% opacity, used for subtle backgrounds."},"notificationOpacity16":{"type":"string","maxLength":64,"description":"Notification color at 16% opacity, used for subtle backgrounds."},"warningColor":{"type":"string","maxLength":64,"description":"Base color used to indicate warning states."},"warningOpacity07":{"type":"string","maxLength":64,"description":"Warning color at 7% opacity, used for subtle backgrounds."},"warningOpacity12":{"type":"string","maxLength":64,"description":"Warning color at 12% opacity, used for subtle backgrounds."},"warningOpacity16":{"type":"string","maxLength":64,"description":"Warning color at 16% opacity, used for subtle backgrounds."},"successColor":{"type":"string","maxLength":64,"description":"Base color used to indicate success states."},"successHover":{"type":"string","maxLength":64,"description":"Success color applied on hover state."},"successPressed":{"type":"string","maxLength":64,"description":"Success color applied on pressed state."},"successOpacity07":{"type":"string","maxLength":64,"description":"Success color at 7% opacity, used for subtle backgrounds."},"successOpacity12":{"type":"string","maxLength":64,"description":"Success color at 12% opacity, used for subtle backgrounds."},"successOpacity16":{"type":"string","maxLength":64,"description":"Success color at 16% opacity, used for subtle backgrounds."},"secondaryColor":{"type":"string","maxLength":64,"description":"Secondary brand color used for supporting UI elements."},"accentColor":{"type":"string","maxLength":64,"description":"Accent color used to highlight key interactive elements."},"fontFamily":{"type":"string","maxLength":100,"description":"Primary font family used across the tenant's branded UI."},"fontFamilyLight":{"type":"string","maxLength":100,"description":"Light-weight variant of the font family, used for secondary text."},"fontFamilyHeading":{"type":"string","maxLength":100,"description":"Font family used for headings."},"isDark":{"type":"boolean","description":"Indicates whether the tenant's branding uses a dark theme."}}},"CreateTenantResponse":{"type":"object","properties":{"id":{"type":"string","description":"Tenant unique ID"}},"required":["id"]}}},"paths":{"/api/v1/tenants":{"post":{"description":"Creates the tenant in the Control API, then an organization in Keycloak,then in identity-pool if enabled. ","operationId":"TenantsController_register_api/v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTenantRequest"}}}},"responses":{"201":{"description":"When the tenant, its operator organization and — when the Identity Pool is enabled — its Identity Pool entry all exist. The returned id is the tenant uuid, not the organization id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTenantResponse"}}}},"400":{"description":"When the tenant name or email address is missing or malformed, when the name derives no usable alias, or when accessExpiresAt is not a valid date or is not in the future."},"401":{"description":"When the agents-realm token is missing or invalid, or belongs to a client other than the Service Provider."},"404":{"description":"When the caller is a Tenant rather than the Service Provider."},"409":{"description":"When this registration is already complete"},"500":{"description":"When registration in the Control API fails."},"502":{"description":"When Keycloak creates the operator organization without returning its id."},"503":{"description":"When part of the registration did not land. Re-sending the same request finishes it; a permanent rejection from the Control API is propagated verbatim instead."}},"summary":"Register a tenant for an operator","tags":["Tenants"]}}}}
```

## Get the tenant linked to the authenticated user

> Resolves the Tenant data for the authenticated admin user (from the token's tenantId claim).

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"tenant":[]}],"components":{"securitySchemes":{"tenant":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Tenant. Token of a Tenant machine client or of a Tenant portal user, carrying the `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"GetTenantResponse":{"type":"object","properties":{"slug":{"type":"string","description":"URL-friendly tenant slug, the alias the platform identifies the tenant by"},"name":{"type":"string","description":"Tenant display name"},"email":{"type":"string","description":"Email address of the operator who owns the tenant."},"environment":{"type":"string","description":"Environment the tenant operates in.","enum":["sandbox","production"]},"accessExpiresAt":{"type":"object","description":"Tenant expiration date; null when its access never expires.","nullable":true},"brandingMetadata":{"description":"Tenant branding metadata","allOf":[{"$ref":"#/components/schemas/TenantBrandingMetadata"}]},"issuer":{"type":"object","description":"Issuer of the tenant's external identity provider; null when no provider is configured.","nullable":true}},"required":["slug","name","email","environment","accessExpiresAt","issuer"]},"TenantBrandingMetadata":{"type":"object","properties":{"primaryColor":{"type":"string","maxLength":64,"description":"Primary brand color used for CTAs and key UI elements."},"primaryColorHover":{"type":"string","maxLength":64,"description":"Primary brand color applied on hover state."},"primaryColorPressed":{"type":"string","maxLength":64,"description":"Primary brand color applied on pressed/active state."},"primaryOpacity08":{"type":"string","maxLength":64,"description":"Primary brand color at 8% opacity, used for subtle backgrounds."},"primaryOpacity16":{"type":"string","maxLength":64,"description":"Primary brand color at 16% opacity, used for subtle backgrounds."},"primaryOpacity20":{"type":"string","maxLength":64,"description":"Primary brand color at 20% opacity, used for subtle backgrounds."},"primaryDisabled":{"type":"string","maxLength":64,"description":"Primary brand color applied to disabled UI elements."},"darkOpacity05":{"type":"string","maxLength":64,"description":"Dark overlay color at 5% opacity."},"darkOpacity08":{"type":"string","maxLength":64,"description":"Dark overlay color at 8% opacity."},"darkOpacity12":{"type":"string","maxLength":64,"description":"Dark overlay color at 12% opacity."},"darkDivider":{"type":"string","maxLength":64,"description":"Dark color used for borders and dividers."},"darkOutlineMedium":{"type":"string","maxLength":64,"description":"Dark medium-emphasis color used for outlines."},"darkOutlineHigh":{"type":"string","maxLength":64,"description":"Dark high-emphasis color used for outlines."},"onSurfaceDarkHighEmphasis":{"type":"string","maxLength":64,"description":"Dark high-emphasis text/icon color rendered on light surfaces."},"onSurfaceDarkMediumEmphasis":{"type":"string","maxLength":64,"description":"Dark medium-emphasis text/icon color rendered on light surfaces."},"onSurfaceDarkDisabled":{"type":"string","maxLength":64,"description":"Dark disabled text/icon color rendered on light surfaces."},"onSurfaceLightHighEmphasis":{"type":"string","maxLength":64,"description":"Light high-emphasis text/icon color rendered on dark surfaces."},"onSurfaceLightMediumEmphasis":{"type":"string","maxLength":64,"description":"Light medium-emphasis text/icon color rendered on dark surfaces."},"onSurfaceLightDisabled":{"type":"string","maxLength":64,"description":"Light disabled text/icon color rendered on dark surfaces."},"textOnSurface":{"type":"string","maxLength":64,"description":"Default text color rendered on top of a surface background."},"surfaceNull":{"type":"string","maxLength":64,"description":"Base surface color with no elevation applied."},"cardBg":{"type":"string","maxLength":64,"description":"Background color used for card components."},"cardStroke":{"type":"string","maxLength":64,"description":"Border/stroke color used around card components."},"surface1":{"type":"string","maxLength":64,"description":"Elevation level 1 surface color."},"surface2":{"type":"string","maxLength":64,"description":"Elevation level 2 surface color."},"surface3":{"type":"string","maxLength":64,"description":"Elevation level 3 surface color."},"surface4":{"type":"string","maxLength":64,"description":"Elevation level 4 surface color."},"surface5":{"type":"string","maxLength":64,"description":"Elevation level 5 surface color."},"surfaceGrey1":{"type":"string","maxLength":64,"description":"Grey surface tone, level 1."},"surfaceGrey2":{"type":"string","maxLength":64,"description":"Grey surface tone, level 2."},"surfaceGrey3":{"type":"string","maxLength":64,"description":"Grey surface tone, level 3."},"surfaceGrey4":{"type":"string","maxLength":64,"description":"Grey surface tone, level 4."},"surfaceGrey5":{"type":"string","maxLength":64,"description":"Grey surface tone, level 5."},"shutterDark70":{"type":"string","maxLength":64,"description":"Dark modal/overlay shutter color at 70% opacity."},"shutterDark30":{"type":"string","maxLength":64,"description":"Dark modal/overlay shutter color at 30% opacity."},"shutterLight32":{"type":"string","maxLength":64,"description":"Light modal/overlay shutter color at 32% opacity."},"shutterLight75":{"type":"string","maxLength":64,"description":"Light modal/overlay shutter color at 75% opacity."},"linkColor":{"type":"string","maxLength":64,"description":"Color applied to hyperlinks."},"widgetColor":{"type":"string","maxLength":64,"description":"Base color used for embedded widget backgrounds."},"widgetColorHover":{"type":"string","maxLength":64,"description":"Embedded widget accent color applied on hover state."},"widgetColorPressed":{"type":"string","maxLength":64,"description":"Embedded widget accent color applied on pressed state."},"notificationColor":{"type":"string","maxLength":64,"description":"Base color used to indicate error states."},"notificationHover":{"type":"string","maxLength":64,"description":"Notification color applied on hover state."},"notificationPressed":{"type":"string","maxLength":64,"description":"Notification color applied on pressed state."},"notificationOpacity08":{"type":"string","maxLength":64,"description":"Notification color at 8% opacity, used for subtle backgrounds."},"notificationOpacity12":{"type":"string","maxLength":64,"description":"Notification color at 12% opacity, used for subtle backgrounds."},"notificationOpacity16":{"type":"string","maxLength":64,"description":"Notification color at 16% opacity, used for subtle backgrounds."},"warningColor":{"type":"string","maxLength":64,"description":"Base color used to indicate warning states."},"warningOpacity07":{"type":"string","maxLength":64,"description":"Warning color at 7% opacity, used for subtle backgrounds."},"warningOpacity12":{"type":"string","maxLength":64,"description":"Warning color at 12% opacity, used for subtle backgrounds."},"warningOpacity16":{"type":"string","maxLength":64,"description":"Warning color at 16% opacity, used for subtle backgrounds."},"successColor":{"type":"string","maxLength":64,"description":"Base color used to indicate success states."},"successHover":{"type":"string","maxLength":64,"description":"Success color applied on hover state."},"successPressed":{"type":"string","maxLength":64,"description":"Success color applied on pressed state."},"successOpacity07":{"type":"string","maxLength":64,"description":"Success color at 7% opacity, used for subtle backgrounds."},"successOpacity12":{"type":"string","maxLength":64,"description":"Success color at 12% opacity, used for subtle backgrounds."},"successOpacity16":{"type":"string","maxLength":64,"description":"Success color at 16% opacity, used for subtle backgrounds."},"secondaryColor":{"type":"string","maxLength":64,"description":"Secondary brand color used for supporting UI elements."},"accentColor":{"type":"string","maxLength":64,"description":"Accent color used to highlight key interactive elements."},"fontFamily":{"type":"string","maxLength":100,"description":"Primary font family used across the tenant's branded UI."},"fontFamilyLight":{"type":"string","maxLength":100,"description":"Light-weight variant of the font family, used for secondary text."},"fontFamilyHeading":{"type":"string","maxLength":100,"description":"Font family used for headings."},"isDark":{"type":"boolean","description":"Indicates whether the tenant's branding uses a dark theme."}}}}},"paths":{"/api/v1/tenants/me":{"get":{"description":"Resolves the Tenant data for the authenticated admin user (from the token's tenantId claim).","operationId":"TenantsController_getCurrent_api/v1","parameters":[],"responses":{"200":{"description":"When the tenant data is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTenantResponse"}}}},"401":{"description":"When the operator-portal-ui token is missing or invalid, or when it carries no tenantId claim and belongs to a client other than the Service Provider."},"404":{"description":"- When the caller is the Service Provider rather than a tenant operator. A portal token that simply carries no tenantId claim is rejected earlier, with a 401.\n- When no tenant is registered under the tenantId on the token."},"500":{"description":"When the Keycloak Admin API request fails."}},"summary":"Get the tenant linked to the authenticated user","tags":["Tenants"]}}}}
```

## Update the tenant

> Resolves the Tenant machine client linked to the authenticated user and updates its tenant in the Control API.

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"tenant":[]}],"components":{"securitySchemes":{"tenant":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Tenant. Token of a Tenant machine client or of a Tenant portal user, carrying the `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"UpdateTenantRequest":{"type":"object","properties":{"name":{"type":"string","description":"New display name of the tenant"},"brandingMetadata":{"description":"Tenant branding metadata. Preserved when omitted.","allOf":[{"$ref":"#/components/schemas/TenantBrandingMetadata"}]}},"required":["name"]},"TenantBrandingMetadata":{"type":"object","properties":{"primaryColor":{"type":"string","maxLength":64,"description":"Primary brand color used for CTAs and key UI elements."},"primaryColorHover":{"type":"string","maxLength":64,"description":"Primary brand color applied on hover state."},"primaryColorPressed":{"type":"string","maxLength":64,"description":"Primary brand color applied on pressed/active state."},"primaryOpacity08":{"type":"string","maxLength":64,"description":"Primary brand color at 8% opacity, used for subtle backgrounds."},"primaryOpacity16":{"type":"string","maxLength":64,"description":"Primary brand color at 16% opacity, used for subtle backgrounds."},"primaryOpacity20":{"type":"string","maxLength":64,"description":"Primary brand color at 20% opacity, used for subtle backgrounds."},"primaryDisabled":{"type":"string","maxLength":64,"description":"Primary brand color applied to disabled UI elements."},"darkOpacity05":{"type":"string","maxLength":64,"description":"Dark overlay color at 5% opacity."},"darkOpacity08":{"type":"string","maxLength":64,"description":"Dark overlay color at 8% opacity."},"darkOpacity12":{"type":"string","maxLength":64,"description":"Dark overlay color at 12% opacity."},"darkDivider":{"type":"string","maxLength":64,"description":"Dark color used for borders and dividers."},"darkOutlineMedium":{"type":"string","maxLength":64,"description":"Dark medium-emphasis color used for outlines."},"darkOutlineHigh":{"type":"string","maxLength":64,"description":"Dark high-emphasis color used for outlines."},"onSurfaceDarkHighEmphasis":{"type":"string","maxLength":64,"description":"Dark high-emphasis text/icon color rendered on light surfaces."},"onSurfaceDarkMediumEmphasis":{"type":"string","maxLength":64,"description":"Dark medium-emphasis text/icon color rendered on light surfaces."},"onSurfaceDarkDisabled":{"type":"string","maxLength":64,"description":"Dark disabled text/icon color rendered on light surfaces."},"onSurfaceLightHighEmphasis":{"type":"string","maxLength":64,"description":"Light high-emphasis text/icon color rendered on dark surfaces."},"onSurfaceLightMediumEmphasis":{"type":"string","maxLength":64,"description":"Light medium-emphasis text/icon color rendered on dark surfaces."},"onSurfaceLightDisabled":{"type":"string","maxLength":64,"description":"Light disabled text/icon color rendered on dark surfaces."},"textOnSurface":{"type":"string","maxLength":64,"description":"Default text color rendered on top of a surface background."},"surfaceNull":{"type":"string","maxLength":64,"description":"Base surface color with no elevation applied."},"cardBg":{"type":"string","maxLength":64,"description":"Background color used for card components."},"cardStroke":{"type":"string","maxLength":64,"description":"Border/stroke color used around card components."},"surface1":{"type":"string","maxLength":64,"description":"Elevation level 1 surface color."},"surface2":{"type":"string","maxLength":64,"description":"Elevation level 2 surface color."},"surface3":{"type":"string","maxLength":64,"description":"Elevation level 3 surface color."},"surface4":{"type":"string","maxLength":64,"description":"Elevation level 4 surface color."},"surface5":{"type":"string","maxLength":64,"description":"Elevation level 5 surface color."},"surfaceGrey1":{"type":"string","maxLength":64,"description":"Grey surface tone, level 1."},"surfaceGrey2":{"type":"string","maxLength":64,"description":"Grey surface tone, level 2."},"surfaceGrey3":{"type":"string","maxLength":64,"description":"Grey surface tone, level 3."},"surfaceGrey4":{"type":"string","maxLength":64,"description":"Grey surface tone, level 4."},"surfaceGrey5":{"type":"string","maxLength":64,"description":"Grey surface tone, level 5."},"shutterDark70":{"type":"string","maxLength":64,"description":"Dark modal/overlay shutter color at 70% opacity."},"shutterDark30":{"type":"string","maxLength":64,"description":"Dark modal/overlay shutter color at 30% opacity."},"shutterLight32":{"type":"string","maxLength":64,"description":"Light modal/overlay shutter color at 32% opacity."},"shutterLight75":{"type":"string","maxLength":64,"description":"Light modal/overlay shutter color at 75% opacity."},"linkColor":{"type":"string","maxLength":64,"description":"Color applied to hyperlinks."},"widgetColor":{"type":"string","maxLength":64,"description":"Base color used for embedded widget backgrounds."},"widgetColorHover":{"type":"string","maxLength":64,"description":"Embedded widget accent color applied on hover state."},"widgetColorPressed":{"type":"string","maxLength":64,"description":"Embedded widget accent color applied on pressed state."},"notificationColor":{"type":"string","maxLength":64,"description":"Base color used to indicate error states."},"notificationHover":{"type":"string","maxLength":64,"description":"Notification color applied on hover state."},"notificationPressed":{"type":"string","maxLength":64,"description":"Notification color applied on pressed state."},"notificationOpacity08":{"type":"string","maxLength":64,"description":"Notification color at 8% opacity, used for subtle backgrounds."},"notificationOpacity12":{"type":"string","maxLength":64,"description":"Notification color at 12% opacity, used for subtle backgrounds."},"notificationOpacity16":{"type":"string","maxLength":64,"description":"Notification color at 16% opacity, used for subtle backgrounds."},"warningColor":{"type":"string","maxLength":64,"description":"Base color used to indicate warning states."},"warningOpacity07":{"type":"string","maxLength":64,"description":"Warning color at 7% opacity, used for subtle backgrounds."},"warningOpacity12":{"type":"string","maxLength":64,"description":"Warning color at 12% opacity, used for subtle backgrounds."},"warningOpacity16":{"type":"string","maxLength":64,"description":"Warning color at 16% opacity, used for subtle backgrounds."},"successColor":{"type":"string","maxLength":64,"description":"Base color used to indicate success states."},"successHover":{"type":"string","maxLength":64,"description":"Success color applied on hover state."},"successPressed":{"type":"string","maxLength":64,"description":"Success color applied on pressed state."},"successOpacity07":{"type":"string","maxLength":64,"description":"Success color at 7% opacity, used for subtle backgrounds."},"successOpacity12":{"type":"string","maxLength":64,"description":"Success color at 12% opacity, used for subtle backgrounds."},"successOpacity16":{"type":"string","maxLength":64,"description":"Success color at 16% opacity, used for subtle backgrounds."},"secondaryColor":{"type":"string","maxLength":64,"description":"Secondary brand color used for supporting UI elements."},"accentColor":{"type":"string","maxLength":64,"description":"Accent color used to highlight key interactive elements."},"fontFamily":{"type":"string","maxLength":100,"description":"Primary font family used across the tenant's branded UI."},"fontFamilyLight":{"type":"string","maxLength":100,"description":"Light-weight variant of the font family, used for secondary text."},"fontFamilyHeading":{"type":"string","maxLength":100,"description":"Font family used for headings."},"isDark":{"type":"boolean","description":"Indicates whether the tenant's branding uses a dark theme."}}}}},"paths":{"/api/v1/tenants/me":{"put":{"description":"Resolves the Tenant machine client linked to the authenticated user and updates its tenant in the Control API.","operationId":"TenantsController_update_api/v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTenantRequest"}}}},"responses":{"204":{"description":"When the tenant name or branding metadata are updated."},"401":{"description":"When the operator-portal-ui token is missing or invalid, or when it carries no tenantId claim and belongs to a client other than the Service Provider."},"404":{"description":"- When the caller is the Service Provider rather than a tenant operator. A portal token that simply carries no tenantId claim is rejected earlier, with a 401.\n- When no tenant is registered under the tenantId on the token."},"409":{"description":"When another tenant already uses the requested name."},"500":{"description":"When the Control API update or the Keycloak Admin lookup fails."}},"summary":"Update the tenant","tags":["Tenants"]}}}}
```

## Get the machine client of the tenant linked to the authenticated user

> Resolves the Tenant machine client from the token's tenantId claim and returns its client id. Answers 404 while the client has not been created.

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"tenant":[]}],"components":{"securitySchemes":{"tenant":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Tenant. Token of a Tenant machine client or of a Tenant portal user, carrying the `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"GetTenantClientResponse":{"type":"object","properties":{"clientId":{"type":"string","description":"The Tenant machine client id (format: tenant:{uuid})"}},"required":["clientId"]}}},"paths":{"/api/v1/tenants/me/client":{"get":{"description":"Resolves the Tenant machine client from the token's tenantId claim and returns its client id. Answers 404 while the client has not been created.","operationId":"TenantsController_getCurrentClient_api/v1","parameters":[],"responses":{"200":{"description":"When the machine client id of the tenant is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTenantClientResponse"}}}},"401":{"description":"When the operator-portal-ui token is missing or invalid, or when it carries no tenantId claim and belongs to a client other than the Service Provider."},"404":{"description":"- When the caller is the Service Provider rather than a tenant operator. A portal token that simply carries no tenantId claim is rejected earlier, with a 401.\n- When the tenant's machine client has not been created yet."},"500":{"description":"When the Keycloak Admin API request fails."}},"summary":"Get the machine client of the tenant linked to the authenticated user","tags":["Tenants"]}}}}
```

## Create the tenant machine client

> Creates the Tenant's Keycloak machine client and returns its credentials. The Tenant is resolved from the token's tenantId claim.

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"tenant":[]}],"components":{"securitySchemes":{"tenant":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Tenant. Token of a Tenant machine client or of a Tenant portal user, carrying the `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"CreateTenantClientResponse":{"type":"object","properties":{"clientId":{"type":"string","description":"The generated Tenant machine client id (format: tenant:{uuid})"},"clientSecret":{"type":"string","description":"The generated Tenant machine client secret"}},"required":["clientId","clientSecret"]}}},"paths":{"/api/v1/tenants/me/client":{"post":{"description":"Creates the Tenant's Keycloak machine client and returns its credentials. The Tenant is resolved from the token's tenantId claim.","operationId":"TenantsController_createClient_api/v1","parameters":[],"responses":{"201":{"description":"When the machine client is created and its credentials are returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTenantClientResponse"}}}},"401":{"description":"When the operator-portal-ui token is missing or invalid, or when it carries no tenantId claim and belongs to a client other than the Service Provider."},"404":{"description":"- When the caller is the Service Provider rather than a tenant operator. A portal token that simply carries no tenantId claim is rejected earlier, with a 401.\n- When no tenant is registered under the tenantId on the token."},"409":{"description":"When the tenant's machine client already exists."},"500":{"description":"When the machine client could not be provisioned in Keycloak. Control API failures propagate the upstream status code."}},"summary":"Create the tenant machine client","tags":["Tenants"]}}}}
```

## Regenerate the tenant client secret

> Resolves the Tenant machine client linked to the authenticated user, verifies the tenant exists in the Control API, and regenerates its Keycloak client secret.

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"tenant":[]}],"components":{"securitySchemes":{"tenant":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Tenant. Token of a Tenant machine client or of a Tenant portal user, carrying the `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"RotateClientSecretResponse":{"type":"object","properties":{"clientSecret":{"type":"string","description":"The regenerated Tenant machine client secret"}},"required":["clientSecret"]}}},"paths":{"/api/v1/tenants/me/client-secret":{"post":{"description":"Resolves the Tenant machine client linked to the authenticated user, verifies the tenant exists in the Control API, and regenerates its Keycloak client secret.","operationId":"TenantsController_rotateClientSecret_api/v1","parameters":[],"responses":{"200":{"description":"When the client secret is regenerated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateClientSecretResponse"}}}},"401":{"description":"When the operator-portal-ui token is missing or invalid, or when it carries no tenantId claim and belongs to a client other than the Service Provider."},"404":{"description":"- When the caller is the Service Provider rather than a tenant operator. A portal token that simply carries no tenantId claim is rejected earlier, with a 401.\n- When no tenant is registered under the tenantId on the token."},"500":{"description":"When the Keycloak Admin API request fails."}},"summary":"Regenerate the tenant client secret","tags":["Tenants"]}}}}
```

## Get the tenant's external identity provider

> Returns what was passed during inital configuration, except for clientSecret.

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"tenant":[]}],"components":{"securitySchemes":{"tenant":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Tenant. Token of a Tenant machine client or of a Tenant portal user, carrying the `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"GetExtIdpResponse":{"type":"object","properties":{"clientId":{"type":"string","description":"OAuth client identifier this platform uses when brokering to the provider"},"discoveryUrl":{"type":"string","description":"OpenID Provider Metadata URL the configuration was derived from"}},"required":["clientId","discoveryUrl"]}}},"paths":{"/api/v1/tenants/me/ext-idp":{"get":{"description":"Returns what was passed during inital configuration, except for clientSecret.","operationId":"TenantsController_getExtIdp_api/v1","parameters":[],"responses":{"200":{"description":"When the external identity provider configuration is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetExtIdpResponse"}}}},"401":{"description":"When the operator-portal-ui token is missing or invalid, or when it carries no tenantId claim and belongs to a client other than the Service Provider."},"404":{"description":"- When no tenant is registered under the tenantId on the token, or no external identity provider has been configured for the tenant.\n- When an earlier configuration attempt did not finish: the identity provider exists but is not linked to a tenant organization. Sending the configuration again completes it."},"500":{"description":"When a Keycloak Admin API request fails. GA Control failures propagate upstream."}},"summary":"Get the tenant's external identity provider","tags":["Tenants"]}}}}
```

## Register the tenant's external identity provider

> Creates ext IdP, its mappers, and creates org and links the IdP to this org

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"tenant":[]}],"components":{"securitySchemes":{"tenant":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Tenant. Token of a Tenant machine client or of a Tenant portal user, carrying the `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"UpsertExtIdpRequest":{"type":"object","properties":{"discoveryUrl":{"type":"string","description":"OpenID Provider Metadata URL of the tenant's identity provider, typically ending in .well-known/openid-configuration. Fetched server-side to derive the brokered endpoints."},"clientId":{"type":"string","description":"OAuth client identifier this platform uses when brokering to the provider"},"clientSecret":{"type":"string","description":"OAuth client secret paired with clientId. Write-only; never read back."}},"required":["discoveryUrl","clientId","clientSecret"]}}},"paths":{"/api/v1/tenants/me/ext-idp":{"put":{"description":"Creates ext IdP, its mappers, and creates org and links the IdP to this org","operationId":"TenantsController_upsertExtIdp_api/v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertExtIdpRequest"}}}},"responses":{"204":{"description":"When the identity provider, its mappers, the organization and their link are all in place."},"400":{"description":"When the discovery URL or the client credentials are missing or malformed, when the discovery document cannot be retrieved, or when it omits an endpoint required to broker to the provider."},"401":{"description":"When the operator-portal-ui token is missing or invalid, or when it carries no tenantId claim and belongs to a client other than the Service Provider."},"404":{"description":"- When the caller is the Service Provider rather than a tenant operator. A portal token that simply carries no tenantId claim is rejected earlier, with a 401.\n- When no tenant is registered under the tenantId on the token."},"500":{"description":"When a Keycloak Admin API request fails. GA Control failures propagate upstream."}},"summary":"Register the tenant's external identity provider","tags":["Tenants"]}}}}
```

## Remove the tenant's external identity provider

> Removes what was created by PUT request: mappers, IdP, org. Unlinks org and IdP first.

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"tenant":[]}],"components":{"securitySchemes":{"tenant":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Tenant. Token of a Tenant machine client or of a Tenant portal user, carrying the `tenantId` claim. Authorize one bearer scheme at a time."}}},"paths":{"/api/v1/tenants/me/ext-idp":{"delete":{"description":"Removes what was created by PUT request: mappers, IdP, org. Unlinks org and IdP first.","operationId":"TenantsController_deleteExtIdp_api/v1","parameters":[],"responses":{"204":{"description":"When the identity provider, its mappers, the organization and their link have all been removed. Also returned when the tenant had nothing configured, since the operation is idempotent."},"401":{"description":"When the operator-portal-ui token is missing or invalid, or when it carries no tenantId claim and belongs to a client other than the Service Provider."},"404":{"description":"- When the caller is the Service Provider rather than a tenant operator. A portal token that simply carries no tenantId claim is rejected earlier, with a 401.\n- When no tenant is registered under the tenantId on the token."},"500":{"description":"When a Keycloak Admin API request fails. GA Control failures propagate upstream."}},"summary":"Remove the tenant's external identity provider","tags":["Tenants"]}}}}
```

## Set Tenant expiry

> The date is written to the Control API and to the Tenant's Keycloak organizations.\
> &#x20;   This endpoint is operator-sp only.

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"sp":[]}],"components":{"securitySchemes":{"sp":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Service Provider. Token of the Service Provider client in the `agents` realm, with no `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"UpdateAccessExpiryRequest":{"type":"object","properties":{"accessExpiresAt":{"type":"object","description":"Tenant expiration date. Send null so its access never expires. Tokens issued before this call keep the expiry they were minted with.","nullable":true}},"required":["accessExpiresAt"]}}},"paths":{"/api/v1/tenants/{id}/access-expiry":{"put":{"description":"The date is written to the Control API and to the Tenant's Keycloak organizations.\n    This endpoint is operator-sp only.","operationId":"TenantsController_updateAccessExpiry_api/v1","parameters":[{"name":"id","required":true,"in":"path","description":"Tenant unique ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAccessExpiryRequest"}}}},"responses":{"204":{"description":"When the expiry is written to the Control API and to the tenant organizations. Tokens issued before this call keep the expiry they were minted with."},"400":{"description":"When the tenant id is not a uuid, or accessExpiresAt is missing, is neither null nor an ISO 8601 timestamp, or is an ISO 8601 form that names no single moment in time."},"401":{"description":"When the agents-realm token is missing or invalid, or belongs to a client other than the Service Provider."},"404":{"description":"When no tenant is registered under this id, or when the caller is a Tenant rather than the Service Provider."},"503":{"description":"When the expiry reached some of Keycloak and the Control API but not all of it. The write order leaves the platform stricter than its record, and re-sending the same value repairs it."}},"summary":"Set Tenant expiry","tags":["Tenants"]}}}}
```

## Get which wallet clients a tenant may reach

> operator-sp only endpoint that returns the webCwEnabled access flag for the specified Tenant.

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"sp":[]}],"components":{"securitySchemes":{"sp":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Service Provider. Token of the Service Provider client in the `agents` realm, with no `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"GetWalletAccessResponse":{"type":"object","properties":{"webCwEnabled":{"type":"boolean","description":"Whether the tenant may reach the web custodial wallet UI"}},"required":["webCwEnabled"]}}},"paths":{"/api/v1/tenants/{id}/wallet-access":{"get":{"description":"operator-sp only endpoint that returns the webCwEnabled access flag for the specified Tenant.","operationId":"TenantsController_getWalletAccess_api/v1","parameters":[{"name":"id","required":true,"in":"path","description":"Tenant unique ID","schema":{"type":"string"}}],"responses":{"200":{"description":"When the wallet access flags are returned. A tenant with no Keycloak organization yet answers with every flag disabled rather than a 404.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetWalletAccessResponse"}}}},"400":{"description":"When the tenant id is not a uuid."},"401":{"description":"When the agents-realm token is missing or invalid, or belongs to a client other than the Service Provider."},"404":{"description":"When no tenant exists with this id, or when the caller is a Tenant rather than the Service Provider."},"500":{"description":"When a Keycloak Admin API request fails. GA Control failures propagate upstream."}},"summary":"Get which wallet clients a tenant may reach","tags":["Tenants"]}}}}
```

## Set which wallet clients a tenant may reach

> Updates the webCwEnabled wallet-access flag for the specified Tenant\
> &#x20;   This endpoint is operator-sp only, and cannot be accessed by the Tenant

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Identity Manager Documentation","version":"0.1.2"},"tags":[{"name":"Tenants","description":""}],"security":[{"sp":[]}],"components":{"securitySchemes":{"sp":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Service Provider. Token of the Service Provider client in the `agents` realm, with no `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"UpdateWalletAccessRequest":{"type":"object","properties":{"webCwEnabled":{"type":"boolean","description":"Whether the tenant may reach the web custodial wallet UI"}},"required":["webCwEnabled"]}}},"paths":{"/api/v1/tenants/{id}/wallet-access":{"put":{"description":"Updates the webCwEnabled wallet-access flag for the specified Tenant\n    This endpoint is operator-sp only, and cannot be accessed by the Tenant","operationId":"TenantsController_updateWalletAccess_api/v1","parameters":[{"name":"id","required":true,"in":"path","description":"Tenant unique ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWalletAccessRequest"}}}},"responses":{"204":{"description":"When the wallet access flags are written to the tenant organization."},"400":{"description":"When the tenant id is not a uuid, or either access flag is missing or not a boolean."},"401":{"description":"When the agents-realm token is missing or invalid, or belongs to a client other than the Service Provider."},"404":{"description":"When no tenant exists with this id, when it has no Keycloak organization yet, or when the caller is a Tenant rather than the Service Provider."},"500":{"description":"When a Keycloak Admin API request fails. GA Control failures propagate upstream."}},"summary":"Set which wallet clients a tenant may reach","tags":["Tenants"]}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.toolkit.equs.ai/api/identity-manager-api/tenants.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
