> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wellapp.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Workspace

> A Workspace is the top-level multi-tenant boundary in the Well platform

A Workspace is the top-level multi-tenant boundary in the Well platform. It represents a single business entity's operational context and is the root scope for all domain resources — companies, invoices, transactions, memberships, connectors, webhooks, and accounting settings. Workspaces may form parent-child hierarchies (e.g. a holding company with subsidiary workspaces) and may belong to workspace groups for cross-workspace reporting. Every other resource in the platform carries a `workspace_id` foreign key, making the Workspace the primary security and tenancy primitive.

| Naming                          | Value            |
| ------------------------------- | ---------------- |
| Object                          | Workspace        |
| Resource type (JSON:API `type`) | `workspace`      |
| Collection / records root       | `workspaces`     |
| REST base                       | `/v1/workspaces` |
| Entity class                    | `Workspace`      |

<Note>
  **Read access today:** this object is readable via the universal `POST /v1/records/query` endpoint with `root: "workspaces"`. A dedicated `GET /v1/workspaces` endpoint is **Planned**.
</Note>

## API operations

| Operation | Method & path                | Status                                             |
| --------- | ---------------------------- | -------------------------------------------------- |
| List      | `GET /v1/workspaces`         | 🟡 Planned <sub>via `POST /v1/records/query`</sub> |
| Retrieve  | `GET /v1/workspaces/{id}`    | ✅ Implemented                                      |
| Create    | `POST /v1/workspaces`        | ✅ Implemented                                      |
| Update    | `PATCH /v1/workspaces/{id}`  | ✅ Implemented                                      |
| Delete    | `DELETE /v1/workspaces/{id}` | ✅ Implemented                                      |

## Data model

### Attributes

| Field                   | Type                                  | Required | Constraints                                            | Allowed values                                                             | Description                                                                                                                                                                                                                   |
| ----------------------- | ------------------------------------- | -------- | ------------------------------------------------------ | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| workspace\_id           | string, UUID, 🔒 system               | ✅ Yes    | unique; generated via gen\_random\_uuid() on insert    | —                                                                          | Public-facing stable identifier for the workspace. Used as the resource address in all API URLs and multi-tenant scoping headers (X-Hasura-Workspace-Id). Never changes after creation.                                       |
| name                    | string                                | ✅ Yes    | NOT NULL                                               | —                                                                          | Display name of the workspace, typically the business name (e.g. 'Acme SAS'). Used in the duplicate-check during workspace creation and as a fuzzy fallback for own\_company resolution when own\_company\_pk is NULL.        |
| description             | string (text)                         | ⚪ No     | nullable                                               | —                                                                          | Optional free-text description of the workspace. Surfaced in workspace settings and admin views.                                                                                                                              |
| trusted                 | boolean                               | ⚪ No     | nullable; default false                                | true \| false                                                              | Internal trust flag. When true, the workspace is treated as a verified / elevated-trust entity for platform-level operations (e.g. connector auto-provisioning). Not exposed to end users via standard workspace settings.    |
| avatar\_color           | string                                | ⚪ No     | nullable                                               | —                                                                          | Hex color code used to render the workspace avatar when no logo media is set. Chosen during workspace creation or updated in settings.                                                                                        |
| external\_workspace\_id | string                                | ⚪ No     | nullable; unique                                       | —                                                                          | Deduplication key for external system references (e.g. Stripe customer IDs, partner platform IDs). Unique constraint prevents double-linking. Used by the partner onboarding flow and external ID-based workspace resolution. |
| timezone                | string                                | ✅ Yes    | columnType text; default 'UTC'                         | Any IANA timezone string (e.g. 'Europe/Paris', 'America/New\_York', 'UTC') | The workspace's canonical timezone used for date rendering, fiscal-period boundaries, report generation, and scheduler jobs. Defaults to UTC on creation; updated during onboarding or workspace settings.                    |
| auto\_extract\_enabled  | boolean                               | ✅ Yes    | default true                                           | true \| false                                                              | Controls whether the document auto-extraction pipeline (AI-powered invoice parsing) runs automatically for this workspace. Can be toggled by workspace owners in settings. Defaults to true on all new workspaces.            |
| enrichment\_config      | object (JSONB)                        | ⚪ No     | nullable; JSONB; shape: \{ auto\_enrich: boolean }     | \{ auto\_enrich: true \| false }                                           | JSONB configuration blob governing the enrichment pipeline behaviour for this workspace. auto\_enrich: true enables automatic company/person enrichment when new records are created.                                         |
| task\_config            | object (JSONB)                        | ⚪ No     | nullable; JSONB; shape: \{ max\_open\_tasks: number }  | \{ max\_open\_tasks: integer >= 0 }                                        | JSONB configuration blob for workspace task management. max\_open\_tasks caps how many concurrent open tasks the system will create for the workspace before requiring human triage.                                          |
| created\_at             | string (ISO 8601 datetime), 🔒 system | ✅ Yes    | set by onCreate lifecycle hook; NOT NULL               | —                                                                          | Timestamp of workspace creation. Set automatically on insert; never updated.                                                                                                                                                  |
| updated\_at             | string (ISO 8601 datetime), 🔒 system | ⚪ No     | set by onCreate and onUpdate lifecycle hooks; nullable | —                                                                          | Timestamp of the most recent update to any workspace property. Managed automatically by the ORM lifecycle hook.                                                                                                               |
| deleted\_at             | string (ISO 8601 datetime)            | ⚪ No     | nullable; soft-delete sentinel                         | null (active) \| ISO 8601 timestamp (soft-deleted)                         | Soft-delete timestamp. When set, the workspace and all its cascade-deleted resources are excluded from standard queries. Hard deletion never occurs; the row persists for audit and data-recovery purposes.                   |

### Relationships

| Name                            | Type                                     | Required | Description                                                                                                                                                                                                                                                                                                                                                                                   |
| ------------------------------- | ---------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| media                           | to-one (media)                           | ⚪ No     | Optional logo or avatar image for the workspace. References a Media entity stored in GCS. When null, the UI falls back to rendering avatar\_color with initials.                                                                                                                                                                                                                              |
| parent\_workspace               | to-one (workspace)                       | ⚪ No     | Self-referential FK for workspace hierarchies. When set, this workspace is a child of the referenced workspace. A partial index idx\_workspaces\_parent covers rows where this is non-null. Parent-workspace admins automatically retain elevated access in child workspaces per the RBAC invariants.                                                                                         |
| own\_company                    | to-one (company)                         | ⚪ No     | The Company record representing the workspace's own legal entity — the business the workspace belongs to. Invoices issued to or from this company are treated as internal. Used by the provider scoring guard to avoid proposing connector tasks for the workspace's own company. Nullable; when null the guard is a no-op and Q1/Q6 counterparty discovery falls back to a name fuzzy-match. |
| child\_workspaces               | to-many (workspace)                      | —        | Inverse collection of all Workspace records whose parent\_workspace points to this workspace. Represents the direct children in the workspace hierarchy. Used by the workspace scope resolver to assemble the descendants array for cross-workspace data views.                                                                                                                               |
| memberships                     | to-many (membership)                     | —        | All Membership records belonging to this workspace, spanning pending and active states. Drives RBAC role resolution: owner, admin, member, guest. Indexed by (workspace, membership\_role, deleted\_at) for hot-path admin lookup.                                                                                                                                                            |
| webhooks                        | to-many (webhook)                        | —        | All Webhook endpoint registrations scoped to this workspace. Webhooks fire on workspace-scoped domain events (invoice created, transaction synced, etc.).                                                                                                                                                                                                                                     |
| workspace\_accounting\_settings | to-one (workspace\_accounting\_settings) | ⚪ No     | One-to-one relationship (inverse side) to the WorkspaceAccountingSettings entity, which carries base\_currency, accounting\_framework, fiscal\_year\_start\_month, tax\_id, registered name, tolerance bands for invoice payment status recompute, and default AR/AP ledger accounts. The owner side lives on WorkspaceAccountingSettings.                                                    |
| workspace\_providers            | to-many (workspace\_provider)            | —        | Junction records linking this workspace to the global Provider catalog entries. Tracks per-workspace provider selection (is\_selected) and match state (is\_matched) for the provider scoring / onboarding flow.                                                                                                                                                                              |

### System-computed

* workspace\_id is generated via gen\_random\_uuid() as a Postgres DEFAULT on insert; the application layer also sets randomUUID() as the JS default, so no manual assignment is needed at any layer.
* created\_at is set by an ORM onCreate lifecycle hook to new Date() on first persist. Never updated.
* updated\_at is set by both onCreate and onUpdate lifecycle hooks — it reflects the timestamp of the most recent ORM flush touching any column.
* deleted\_at is null on active workspaces. Soft-deletion sets this field; every downstream query must filter deleted\_at IS NULL. Hard deletes never occur.
* external\_workspace\_id carries a unique constraint and serves as a stable deduplication key for partner/external integrations. When provided during workspace creation, it prevents duplicate workspace provisioning for the same external customer.
* parent\_workspace\_pk is covered by a partial index idx\_workspaces\_parent filtered to WHERE parent\_workspace\_pk IS NOT NULL. This index is non-trivial only when the hierarchy feature is in use and keeps the hot-path workspace lookup unaffected for flat tenants.
* own\_company is nullable by design. When null, the provider scoring guard is a no-op and counterparty-bank discovery (Q1, Q6) falls back to fuzzy name matching against companies scoped to the workspace — never cross-workspace.
* timezone defaults to 'UTC' at the database level and is updated during workspace onboarding; it governs all date/time rendering, scheduler triggers, and fiscal-period boundary calculations in the platform.
* auto\_extract\_enabled defaults to true; the document extraction pipeline checks this flag before dispatching AI extraction tasks for newly uploaded documents.
* enrichment\_config and task\_config are JSONB blobs with typed TypeScript interfaces (WorkspaceEnrichmentConfig, WorkspaceTaskConfig). They are nullable at the column level; consuming services must null-check before reading nested fields.
* WorkspaceGroupWorkspace join rows reference workspaces by pk with a partial unique index (workspace\_group\_pk, workspace\_pk) WHERE deleted\_at IS NULL — soft-deleted join rows allow legal remove-then-re-add without unique-constraint collisions.

## Example

```json theme={null}
{
  "data": {
    "type": "workspace",
    "id": "b3f2a1e0-4d7c-41aa-9f1b-0c8e3d2b5a6f",
    "attributes": {
      "workspace_id": "b3f2a1e0-4d7c-41aa-9f1b-0c8e3d2b5a6f",
      "name": "Acme SAS",
      "description": "Operating workspace for Acme SAS - European entity",
      "trusted": false,
      "avatar_color": "#3B82F6",
      "external_workspace_id": null,
      "timezone": "Europe/Paris",
      "auto_extract_enabled": true,
      "enrichment_config": {
        "auto_enrich": true
      },
      "task_config": {
        "max_open_tasks": 50
      },
      "created_at": "2025-09-14T08:22:00.000Z",
      "updated_at": "2026-04-03T14:11:45.000Z",
      "deleted_at": null
    },
    "relationships": {
      "media": {
        "data": { "type": "media", "id": "e7a91c30-1234-4bcd-8ef0-aabbcc112233" }
      },
      "parent_workspace": {
        "data": null
      },
      "own_company": {
        "data": { "type": "company", "id": "a1b2c3d4-5678-4abc-9def-000011112222" }
      },
      "child_workspaces": {
        "data": []
      },
      "memberships": {
        "data": [
          { "type": "membership", "id": "f0e1d2c3-b4a5-4678-9012-aabbccddeeff" }
        ]
      },
      "webhooks": {
        "data": []
      },
      "workspace_accounting_settings": {
        "data": { "type": "workspace_accounting_settings", "id": "cc001122-dead-beef-cafe-112233445566" }
      },
      "workspace_providers": {
        "data": []
      }
    }
  }
}
```

<sub>Source: `apps/api/src/database/entities/Workspace.ts` · domain: workspace · tier: Platform</sub>
