---
title: "Create Workspace"
method: POST
path: "/v1/tenants"
tags: ["tenants", "tenants"]
---

# Create Workspace

`POST /v1/tenants`

## Request

- Base URL: `https://api.patricia.app` (the document declares no server; this is the origin it was published from)
- URL: `https://api.patricia.app/v1/tenants`
- Auth: HTTP bearer

Create a new, separate workspace for the authenticated user and return a session scoped to it.

The deliberate way to a second workspace now that the returning-user guard no longer mints one from an
unknown Slack. JWT-only (``require_user``) so it works even from a tenant-less pending session; it never
selects among existing memberships, so it is not the tenant chooser. The required ``Idempotency-Key``
header makes a retry safe: the same key returns the SAME workspace (never a duplicate), and reusing a
key with a different body is a 409. Adopt the returned token pair to enter the new workspace.

## Headers

- `Idempotency-Key` string, required

## Request body

- CreateWorkspaceRequest: Payload for the explicit "create a new / separate workspace" action. An ``Idempotency-Key`` header (required by the route) makes a retry safe. The response is a fresh token pair scoped to the new workspace, which the caller adopts to enter the workspace it just created.
  - `name` string, nullable: Workspace name (a friendly default is used if omitted).

## Response `201`

Successful Response

- TokenResponse: Access + refresh token pair. ``expires_in`` is the access-token lifetime (seconds).
  - `access_token` string, required
  - `refresh_token` string, required
  - `token_type` string
  - `expires_in` integer, required
  - `landing_hint` 'pending_invitation' | 'diverted_unknown_workspace': A non-authorization hint explaining WHY a session landed where it did. The dashboard reads it to show the right next step instead of a bare landing. It never grants access: the token's tenant claim (or its absence) is the sole authority. Two values, and they differ in whether the session has a workspace at all: ``PENDING_INVITATION`` lands TENANT-LESS — a returning user with at least one pending invitation and no active available home. It is NOT "only pending memberships": the branch is chosen on ``has_pending`` before the deactivated/unavailable fallback, so a user holding a pending invite alongside deactivated or unavailable ones lands here too. The SSO guard declines to mint an empty duplicate tenant, and the hint points them at accepting the invite / signing in from the connected workspace. ``DIVERTED_UNKNOWN_WORKSPACE`` lands WITH an active workspace — a returning user who signed in from a chat workspace Patricia does not know. The guard diverts them to their existing primary workspace rather than minting a second one, and the hint is what lets the dashboard say so and offer a deliberate way to create a separate workspace instead of failing silently.
  - `decision_key` string, nullable

## Other responses

- `401`: Unauthorized
- `403`: Email verification required (EMAIL_NOT_VERIFIED)
- `409`: Conflict
- `422`: Validation error

---

[API](https://skmtc.dev/patricia/apis/patricia-api.md) · [All operations](https://skmtc.dev/patricia/apis/patricia-api/llms.txt) · [OpenAPI document](https://skmtc.dev/patricia/apis/patricia-api/revisions/0dfb44495ea1?raw)
