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.
A Journal (record root: journals) represents a named accounting book used to categorize and post financial entries within a workspace — for example, a Sales journal, a Bank journal, or a Miscellaneous journal. It is the top-level organizational unit for double-entry bookkeeping, grouping JournalEntry records beneath it, and optionally carrying default debit/credit LedgerAccount references to pre-fill lines on new entries. Journals are workspace-scoped, soft-deleted, and provisioned either manually or by the financial-pipeline sync (via sourceWorkspaceConnector); the source_entity_id field is the stable provider-side identifier used for idempotent upserts during sync.
| Naming | Value |
|---|
| Object | Journal |
Resource type (JSON:API type) | journal |
| Collection / records root | journals |
| REST base | /v1/journals |
| Entity class | Journal |
API operations
| Operation | Method & path | Status |
|---|
| List | GET /v1/journals | ✅ Implemented |
| Retrieve | GET /v1/journals/{id} | ✅ Implemented |
| Create | POST /v1/journals | 🟡 Planned |
| Update | PATCH /v1/journals/{id} | 🟡 Planned |
| Delete | DELETE /v1/journals/{id} | 🟡 Planned |
Data model
Attributes
| Field | Type | Required | Constraints | Allowed values | Description |
|---|
| journal_id | string, UUID, 🔒 system | ✅ Yes | UNIQUE; generated via gen_random_uuid() on insert | — | Public stable identifier for the journal, exposed in all API responses. Generated server-side; never writable by the client. |
| code | string | ✅ Yes | max length 10; UNIQUE(workspace_pk, code) — plain unique constraint on all rows including soft-deleted ones, enforced at the database level; mirrored by @Unique({ properties: [‘workspace’, ‘code’] }) on the entity | — | Short alphanumeric book code assigned by the workspace or imported from the accounting provider (e.g. ‘VT’ for sales, ‘BQ’ for bank, ‘OD’ for miscellaneous). Must be unique per workspace across all rows. |
| name | string | ✅ Yes | max length 255 | — | Human-readable display label for the journal (e.g. ‘Ventes — Clients France’, ‘Banque Qonto EUR’). |
| journal_type | enum (journal_type_enum) | ✅ Yes | NOT NULL; mapped to PostgreSQL native enum journal_type_enum | BANK, SALES, PURCHASES, MISC, OPENING, CLOSING | Accounting classification of the journal. BANK: cash/bank movement book. SALES: receivables and revenue. PURCHASES: payables and expenses. MISC: catch-all for adjustments. OPENING/CLOSING: period-boundary entries. |
| source_entity_id | string | ⚪ No | nullable; max length 255 (varchar(255) in DDL); PARTIAL UNIQUE INDEX journals_workspace_source_entity_id_unique on (workspace_pk, source_entity_id) WHERE source_entity_id IS NOT NULL AND deleted_at IS NULL — ensures idempotent upserts per provider without conflicting on NULL | — | Stable identifier assigned by the originating financial provider (e.g. Pennylane journal ID). Used by the sync pipeline for deduplication/upsert. NULL for manually created journals. |
| is_active | boolean | ✅ Yes | DEFAULT true; indexed (idx_journals_is_active) | true, false | Whether the journal is currently in use. Inactive journals are hidden from accounting entry creation flows but remain queryable for historical reporting. |
| created_at | Date, 🔒 system | ✅ Yes | NOT NULL DEFAULT now(); set once via MikroORM onCreate lifecycle hook; not writable by client | — | ISO 8601 timestamp of record creation. |
| updated_at | Date, 🔒 system | ✅ Yes | NOT NULL DEFAULT now(); set via MikroORM onCreate + onUpdate lifecycle hooks; not writable by client | — | ISO 8601 timestamp of the last modification. Always set at insert time via DEFAULT now(); refreshed on every ORM flush that touches this entity. |
| deleted_at | Date | ⚪ No | nullable; soft-delete sentinel — all active queries must predicate deleted_at IS NULL | — | ISO 8601 timestamp set when the journal is soft-deleted. NULL means the record is active. Hard deletes are not supported. |
Relationships
| Name | Type | Required | Description |
|---|
| workspace | to-one (workspace) | ✅ Yes | The tenant workspace that owns this journal. All queries must scope to the authenticated workspace; the combination (workspace_pk, code) carries a plain UNIQUE constraint enforcing per-workspace code uniqueness. References core_api.workspaces. |
| default_debit_account | to-one (ledger_account) | ⚪ No | Optional default LedgerAccount pre-filled as the debit leg when creating new JournalEntry lines under this journal. Indexed (idx_journals_default_debit_account). References core_api.ledger_accounts. |
| default_credit_account | to-one (ledger_account) | ⚪ No | Optional default LedgerAccount pre-filled as the credit leg when creating new JournalEntry lines under this journal. References core_api.ledger_accounts. |
| source_workspace_connector | to-one (workspace_connector) | ⚪ No | The WorkspaceConnector sync instance that created or last reconciled this journal record. NULL for manually created journals. Used for provenance tracking and to identify connector-managed records that should not be edited manually. References core_api.workspace_connectors. |
System-computed
journal_id is generated server-side via PostgreSQL gen_random_uuid() (defaultRaw) and mirrored in the ORM entity initializer randomUUID(). Never supplied by the client.
created_at is set once by the MikroORM onCreate lifecycle hook at insert time. The database column is NOT NULL DEFAULT now(). Not writable by the client.
updated_at is set by both onCreate and onUpdate MikroORM lifecycle hooks. The database column is NOT NULL DEFAULT now(), so it is always populated from the moment of insert. Reflects the timestamp of the last ORM flush touching this entity.
deleted_at is null on active records. Set to the current timestamp on soft-delete. All repository queries must include deleted_at: null as a filter predicate.
- The combination
(workspace_pk, code) carries a plain database-level UNIQUE constraint (defined in the DDL as UNIQUE(workspace_pk, code) and mirrored by @Unique({ properties: ['workspace', 'code'] }) on the entity). This constraint applies to all rows, including soft-deleted ones.
source_entity_id carries a PARTIAL UNIQUE INDEX journals_workspace_source_entity_id_unique on (workspace_pk, source_entity_id) WHERE source_entity_id IS NOT NULL AND deleted_at IS NULL. This enables idempotent upserts by the financial sync pipeline without conflicting on NULL values for manually created journals.
sourceWorkspaceConnector (→ source_workspace_connector_pk FK column) is set by the ingestion pipeline when a journal is created via connector sync (e.g. Pennylane). NULL indicates manual creation. Presence signals that the record is pipeline-owned and should not be edited without understanding sync implications. A partial index idx_journals_source_wc on (source_workspace_connector_pk) WHERE source_workspace_connector_pk IS NOT NULL supports provenance queries.
- Journals are reachable from a Company via the Hasura computed field
company_journals(company_row, hasura_session), which traverses the 3-hop path: companies → journal_entry_lines (company_pk) → journal_entries (journal_entry_pk) → journals (journal_pk). No direct company_pk FK exists on the journals table itself.
is_active defaults to true at creation. The pipeline or a workspace admin may flip it to false to retire a journal while preserving historical entries.
Example
{
"data": {
"type": "journal",
"id": "a3f1c2d4-7e8b-4a9c-b5f6-0d1e2f3a4b5c",
"attributes": {
"journal_id": "a3f1c2d4-7e8b-4a9c-b5f6-0d1e2f3a4b5c",
"code": "VT",
"name": "Ventes — Clients France",
"journal_type": "SALES",
"source_entity_id": "pnl_jnl_00042",
"is_active": true,
"created_at": "2026-01-15T09:23:11.000Z",
"updated_at": "2026-03-04T14:07:55.000Z",
"deleted_at": null
},
"relationships": {
"workspace": {
"data": { "type": "workspace", "id": "d5e6f7a8-b9c0-4d1e-a2f3-b4c5d6e7f8a9" }
},
"default_debit_account": {
"data": { "type": "ledger_account", "id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e" }
},
"default_credit_account": {
"data": { "type": "ledger_account", "id": "c2d3e4f5-a6b7-4c8d-9e0f-1a2b3c4d5e6f" }
},
"source_workspace_connector": {
"data": { "type": "workspace_connector", "id": "e3f4a5b6-c7d8-4e9f-a0b1-c2d3e4f5a6b7" }
}
}
}
}
Source: apps/api/src/database/entities/Journal.ts · domain: financial-graph · tier: Main