Skip to content

Switch to a different tenant

POST
/api/v1/tenant/switch
curl --request POST \
--url http://localhost:3000/api/v1/tenant/switch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "organizationId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "duration": "15m", "reason": "example", "fromOrganizationId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "expiresAt": "2026-04-15T12:00:00Z" }'

Switching to a tenant the caller is a member of (a home tenant) creates no switch: any open switch is ended and the response is 204. A superadmin switching into any other tenant must give a reason (3-500 characters); one switch is opened and returned with 201. Not available to API keys.

x-organization-id
string format: uuid

UUID of the organization (tenant) the request acts in. It selects the tenant and grants nothing: the server checks membership or an open tenant switch. Not needed for global operations. A malformed value returns 400. API keys are fixed to their own organization; another organization returns 403. The x-organization-source header grants nothing.

Media typeapplication/json
object
organizationId
required

Target organization ID to switch to

string format: uuid
duration

Duration of the switch

string
default: session
Allowed values: 15m 1h 4h session
reason

Required (3-500 characters after trimming) when switching into a tenant the caller is not a member of; ignored for a home tenant

string
>= 3 characters <= 500 characters
fromOrganizationId

Tenant the caller switches from. Must be a tenant the caller is a member of, or the target of the switch being replaced. Defaults to the current tenant, then the replaced switch target, then the primary membership.

string format: uuid
expiresAt

Custom expiry (ISO 8601) for a switch into a tenant the caller is not a member of: at least 1 minute and at most 72 hours from now. Default: 8 hours. Not allowed together with duration; ignored for a home tenant.

string format: date-time

Switch opened

Media typeapplication/json
object
id
required

Switch record ID

string
userId
required

User ID who performed the switch

string
fromOrgId

Original organization ID

string
fromOrgName

Original organization name

string
toOrgId
required

Target organization ID

string
toOrgName

Target organization name

string
duration

Duration of the switch

string
reason

Reason for switching

string
switchedAt
required

When the switch was performed

string format: date-time
expiresAt

When the switch expires

string format: date-time
returnedAt

When the user returned to default tenant

string format: date-time
isActive
required

Whether the switch is currently active

boolean
Examplegenerated
{
"id": "example",
"userId": "example",
"fromOrgId": "example",
"fromOrgName": "example",
"toOrgId": "example",
"toOrgName": "example",
"duration": "example",
"reason": "example",
"switchedAt": "2026-04-15T12:00:00Z",
"expiresAt": "2026-04-15T12:00:00Z",
"returnedAt": "2026-04-15T12:00:00Z",
"isActive": true
}

Home tenant: any open switch ended, none created

Validation failed, reason missing or too short, or fromOrganizationId not allowed

Forbidden. Standard error body (message in parentheses): the caller is not a member of the organization and has no system role (Not a member of this organization); the organization does not exist (Organization not found) or is inactive (Organization is inactive); the caller is an API key (API key not authorized for this organization, or API keys cannot use tenant switches). Switching is a global operation, so a missing open switch does not apply to this endpoint.

A concurrent switch by the same user won the race