> ## 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.

# WorkspacePostingMapping

> WorkspacePostingMapping encodes a single posting rule that maps a semantic document context (CoA version, semantic role, posting kind, document polarity) to acc

WorkspacePostingMapping encodes a single posting rule that maps a semantic document context (CoA version, semantic role, posting kind, document polarity) to accounting targets (LedgerAccount, TaxRate, Journal) for a workspace. The posting engine writes these rows deterministically or via LLM review; the rule-resolver reads them at journal-entry draft time to auto-classify postings. Each row is scoped to a Workspace and optionally to a specific WorkspaceConnector, with precision modifiers for tax behaviour, counterparty kind, currency, country code, and effective date range. A partial unique index (WHERE deleted\_at IS NULL AND mapping\_status = 'active') prevents duplicate active mappings for the same context tuple.

| Naming                          | Value                             |
| ------------------------------- | --------------------------------- |
| Object                          | WorkspacePostingMapping           |
| Resource type (JSON:API `type`) | `workspace_posting_mapping`       |
| Collection / records root       | — <sub>(not a records root)</sub> |
| REST base                       | `/v1/workspace-posting-mappings`  |
| Entity class                    | `WorkspacePostingMapping`         |

<Note>
  **Internal object.** Not currently exposed on the public REST API. The operations below describe the intended contract.
</Note>

## API operations

| Operation | Method & path                                | Status     |
| --------- | -------------------------------------------- | ---------- |
| List      | `GET /v1/workspace-posting-mappings`         | 🟡 Planned |
| Retrieve  | `GET /v1/workspace-posting-mappings/{id}`    | 🟡 Planned |
| Create    | `POST /v1/workspace-posting-mappings`        | 🟡 Planned |
| Update    | `PATCH /v1/workspace-posting-mappings/{id}`  | 🟡 Planned |
| Delete    | `DELETE /v1/workspace-posting-mappings/{id}` | 🟡 Planned |

## Data model

### Attributes

| Field                           | Type                                                    | Required | Constraints                                                                          | Allowed values                           | Description                                                                                                                                                                    |
| ------------------------------- | ------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| workspace\_posting\_mapping\_id | string (UUID)                                           | ✅ Yes    | UNIQUE                                                                               | —                                        | Public UUID identifying this posting rule. Generated via gen\_random\_uuid() on insert.                                                                                        |
| well\_coa\_version              | string                                                  | ✅ Yes    | max length 32                                                                        | —                                        | Version tag of the Well Chart-of-Accounts taxonomy this mapping targets (e.g. 'v2024').                                                                                        |
| well\_semantic\_role            | string                                                  | ✅ Yes    | max length 100                                                                       | —                                        | Semantic accounting role within the CoA taxonomy (e.g. 'accounts\_payable', 'revenue\_product').                                                                               |
| posting\_kind                   | string                                                  | ✅ Yes    | max length 50                                                                        | —                                        | Kind of source document or transaction driving the posting (e.g. 'invoice', 'bank\_transaction').                                                                              |
| document\_polarity              | string                                                  | ✅ Yes    | max length 50                                                                        | —                                        | Polarity direction of the posting line: whether this rule applies to the debit or credit leg.                                                                                  |
| tax\_behavior                   | string \| null                                          | ⚪ No     | max length 50                                                                        | —                                        | Optional tax inclusion modifier narrowing the rule ('exclusive', 'inclusive', 'none'). NULL means the rule applies regardless of tax behaviour.                                |
| counterparty\_kind              | string \| null                                          | ⚪ No     | max length 50                                                                        | —                                        | Optional counterparty classification narrowing the rule (e.g. 'supplier', 'customer'). NULL matches any counterparty kind.                                                     |
| currency                        | string \| null                                          | ⚪ No     | max length 3                                                                         | —                                        | Optional ISO 4217 currency code narrowing the rule. NULL matches any currency.                                                                                                 |
| country\_code                   | string \| null                                          | ⚪ No     | max length 2                                                                         | —                                        | Optional ISO 3166-1 alpha-2 country code narrowing the rule. NULL matches any country.                                                                                         |
| effective\_from                 | date \| null                                            | ⚪ No     | CHECK: effective\_from \<= effective\_to when both non-NULL                          | —                                        | Inclusive start date from which this rule is effective. NULL means no lower bound. Used in the partial-unique active-context index via COALESCE.                               |
| effective\_to                   | date \| null                                            | ⚪ No     | CHECK: effective\_from \<= effective\_to when both non-NULL                          | —                                        | Exclusive end date after which this rule is no longer effective. NULL means open-ended.                                                                                        |
| mapping\_status                 | 🔒 system — enum (WorkspacePostingMappingStatusEnum)    | ✅ Yes    | default: 'active'; native enum workspace\_posting\_mapping\_status\_enum             | active \| needs\_review \| inactive      | Lifecycle state of this mapping rule. The partial unique index on active-context enforces one active rule per context tuple. Managed by the posting engine.                    |
| confidence                      | string (decimal 4,3) \| null                            | ⚪ No     | CHECK: value IS NULL OR (value >= 0 AND value \<= 1); decimal(4,3)                   | —                                        | Confidence score in \[0.000, 1.000] assigned by the LLM jury or deterministic engine. Stored as decimal(4,3); exposed as string in JSON to preserve precision.                 |
| evidence                        | object (JSONB) \| null                                  | ⚪ No     | —                                                                                    | —                                        | Free-form JSONB payload recording why this mapping was created (matched patterns, rule sources, jury rationale). Shape varies by created\_by value.                            |
| created\_by                     | 🔒 system — enum (WorkspacePostingMappingCreatedByEnum) | ✅ Yes    | default: 'deterministic'; native enum workspace\_posting\_mapping\_created\_by\_enum | deterministic \| manual \| reviewed\_llm | Provenance of this mapping: whether it was produced by a deterministic rule, manual human edit, or an LLM that was subsequently reviewed.                                      |
| mapping\_version                | 🔒 system — integer                                     | ✅ Yes    | default: 1                                                                           | —                                        | Monotonically increasing version counter incremented by the posting engine on each rule revision. Default 1.                                                                   |
| created\_at                     | 🔒 system — datetime                                    | ✅ Yes    | —                                                                                    | —                                        | Timestamp when this mapping was created. Set automatically via onCreate hook.                                                                                                  |
| updated\_at                     | 🔒 system — datetime \| null                            | ⚪ No     | —                                                                                    | —                                        | Timestamp of the last update to this mapping. Set automatically via onUpdate hook.                                                                                             |
| deleted\_at                     | 🔒 system — datetime \| null                            | ⚪ No     | —                                                                                    | —                                        | Soft-delete timestamp. Non-null means the mapping is logically deleted and excluded from the partial unique active-context index. All queries must filter deleted\_at IS NULL. |

### Relationships

| Name                     | Type               | Required | Description                                                                                                                                                                                                                                    |
| ------------------------ | ------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| workspace                | to-one (ManyToOne) | ✅ Yes    | The Workspace this posting rule belongs to. All queries must scope by workspace\_pk. Indexed as part of the role and status composite indexes.                                                                                                 |
| sourceWorkspaceConnector | to-one (ManyToOne) | ⚪ No     | Optional WorkspaceConnector that provided the data driving this rule. NULL means the rule applies generically across all connectors for this workspace. ON DELETE SET NULL — deleting the connector nullifies but does not delete the mapping. |
| ledger\_account          | to-one (ManyToOne) | ⚪ No     | Target LedgerAccount to post to for this context. NULL is valid when the rule's primary purpose is to select only a TaxRate or Journal without specifying a ledger account.                                                                    |
| tax\_rate                | to-one (ManyToOne) | ⚪ No     | Target TaxRate to apply when posting. NULL means no tax rate is assigned by this mapping; the posting engine may inherit or default.                                                                                                           |
| journal                  | to-one (ManyToOne) | ⚪ No     | Target Journal (accounting book) to route journal entries into. NULL defers journal selection to the posting engine's default resolution logic.                                                                                                |

### System-computed

* workspace\_posting\_mapping\_id — generated via gen\_random\_uuid() on insert, exposed as the public API id
* created\_at — set automatically by the MikroORM onCreate hook; never writable after creation
* updated\_at — set automatically by the MikroORM onUpdate hook on every write
* deleted\_at — soft-delete field written by the posting engine on rule retirement; not writable by users
* mapping\_status — managed exclusively by the posting engine (transitions: active → needs\_review → inactive or active → deleted\_at); default 'active' on creation
* mapping\_version — incremented by the posting engine on each rule revision; default 1
* created\_by — set at creation time by the engine to record provenance ('deterministic', 'reviewed\_llm') or set to 'manual' for human-authored rules; not subsequently editable
* confidence — computed and stamped by the LLM jury or deterministic scoring logic; null for fully-deterministic rules
* evidence — populated by the engine with the reasoning payload from the mapping generation run
* sourceWorkspaceConnector provenance — when set, records which connector sync triggered the mapping creation; ON DELETE SET NULL ensures orphan safety on connector removal
* Partial unique index workspace\_posting\_mappings\_active\_context\_unique (WHERE deleted\_at IS NULL AND mapping\_status = 'active') — enforced at the DB layer only; cannot be expressed via MikroORM decorators (COALESCE expressions + partial predicate). The entity comment documents this divergence from schema:fresh.

## Example

```json theme={null}
{
  "data": {
    "type": "workspace_posting_mapping",
    "id": "a3f1c2e4-8b7d-4f9a-b2c1-0d5e6f7a8b9c",
    "attributes": {
      "workspace_posting_mapping_id": "a3f1c2e4-8b7d-4f9a-b2c1-0d5e6f7a8b9c",
      "well_coa_version": "v2024",
      "well_semantic_role": "accounts_payable",
      "posting_kind": "invoice",
      "document_polarity": "debit",
      "tax_behavior": "exclusive",
      "counterparty_kind": "supplier",
      "currency": "EUR",
      "country_code": "FR",
      "effective_from": "2024-01-01",
      "effective_to": null,
      "mapping_status": "active",
      "confidence": "0.950",
      "evidence": {
        "rule_source": "deterministic_coa_bootstrap",
        "matched_patterns": ["vat_fr_20", "supplier_invoice"]
      },
      "created_by": "deterministic",
      "mapping_version": 1,
      "created_at": "2025-05-25T10:00:00.000Z",
      "updated_at": "2025-05-25T10:00:00.000Z",
      "deleted_at": null
    },
    "relationships": {
      "workspace": {
        "data": { "type": "workspace", "id": "b1c2d3e4-0000-0000-0000-000000000001" }
      },
      "source_workspace_connector": {
        "data": null
      },
      "ledger_account": {
        "data": { "type": "ledger_account", "id": "c9d8e7f6-0000-0000-0000-000000000002" }
      },
      "tax_rate": {
        "data": { "type": "tax_rate", "id": "d1e2f3a4-0000-0000-0000-000000000003" }
      },
      "journal": {
        "data": null
      }
    }
  }
}
```

<sub>Source: `apps/api/src/database/entities/WorkspacePostingMapping.ts` · domain: financial-graph · tier: Infrastructure</sub>
