Switch to a different tenant
const url = 'http://localhost:3000/api/v1/tenant/switch';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"organizationId":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","duration":"15m","reason":"example","fromOrganizationId":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","expiresAt":"2026-04-15T12:00:00Z"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}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.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”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.
Request Bodyrequired
Section titled “Request Bodyrequired”object
Target organization ID to switch to
Duration of the switch
Required (3-500 characters after trimming) when switching into a tenant the caller is not a member of; ignored for a home tenant
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.
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.
Responses
Section titled “Responses”Switch opened
object
Switch record ID
User ID who performed the switch
Original organization ID
Original organization name
Target organization ID
Target organization name
Duration of the switch
Reason for switching
When the switch was performed
When the switch expires
When the user returned to default tenant
Whether the switch is currently active
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