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 Custom Column is a per-workspace, per-root virtual column a user adds to a records table (e.g. a ‘Risk level’ column on companies). It holds the column definition only — name, type, position, and the AI/formula/format config — while the computed cell values live in custom_column_values. Custom columns are workspace-scoped and namespaced by records root; they are NOT Hasura columns and NOT governed DATA_VIEW_ROOTS, so they sit behind the records table as an overlay rather than as a queryable entity of their own.
| Naming | Value |
|---|
| Object | Custom Column |
Resource type (JSON:API type) | custom_column |
| Collection / records root | — (not a records root) |
| REST base | /v1/custom-columns |
| Entity class | CustomColumn |
Internal object. Not currently exposed on the public REST API. The operations below describe the intended contract.
API operations
| Operation | Method & path | Status |
|---|
| List | GET /v1/custom-columns | 🟡 Planned |
| Retrieve | GET /v1/custom-columns/{id} | 🟡 Planned |
| Create | POST /v1/custom-columns | 🟡 Planned |
| Update | PATCH /v1/custom-columns/{id} | 🟡 Planned |
| Delete | DELETE /v1/custom-columns/{id} | 🟡 Planned |
Data model
Attributes
| Field | Type | Required | Constraints | Allowed values | Description |
|---|
| custom_column_id | string, UUID, 🔒 system | ✅ Yes | unique; gen_random_uuid() | — | Public identifier of the column definition. Internal pk is never exposed. |
| root | string | ✅ Yes | max 50 chars; part of partial-unique key | A records root (companies, invoices, transactions, …) | The data-view root this column is attached to. Scopes the column to one records table. |
| name | string | ✅ Yes | max 255 chars | — | Human-readable column header shown in the records table. |
| field_key | string | ✅ Yes | max 100 chars; part of partial-unique key; slugified from name | — | Stable machine key for the column, slugified from name at creation. Unique per (workspace, root). |
| type | string (CustomColumnTypeEnum) | ✅ Yes | native enum custom_column_type_enum; default ‘text’ | text, number, amount, single_select, multi_select, ai | Column data type. ‘ai’ (and rules_config-bearing columns) are auto-computed; others may be manually entered. |
| position | number (int) | ⚪ No | default 0 | — | Display order of the column within the records table. |
| icon | string | ⚪ No | max 100 chars; nullable | — | Optional icon identifier rendered in the column header. |
| rules_config | jsonb | ⚪ No | nullable | — | AI compute rules. When set, the column is auto-computed by the enrichment pipeline (Anthropic Haiku) for every record. |
| formula_config | jsonb | ⚪ No | nullable | — | Formula configuration for computed (non-AI) columns. |
| format_config | jsonb | ⚪ No | nullable | — | Display/format configuration (e.g. select options, number format). |
| created_at | ISO 8601, 🔒 system | — | onCreate hook | — | Creation timestamp. |
| updated_at | ISO 8601, 🔒 system | — | onCreate + onUpdate hooks | — | Last-update timestamp. |
| deleted_at | ISO 8601, 🔒 system | — | nullable; soft delete | — | Soft-delete tombstone; null when active. |
Relationships
| Name | Type | Required | Description |
|---|
| workspace | to-one (workspace) | ✅ Yes | Owning workspace — the per-workspace scope of the column. |
| values | to-many (custom_column_value) | ⚪ No | Computed/entered cell values for this column, one per record (cascade-deleted with the column). |
System-computed
- custom_column_id generated by gen_random_uuid()
- field_key slugified from name at creation (slugifyFieldKey)
- Partial unique index on (workspace_pk, root, field_key) WHERE deleted_at IS NULL — managed in a raw-SQL migration, not @Index (MikroORM cannot express partial indexes)
- type defaults to ‘text’; position defaults to 0
- created_at via onCreate; updated_at via onCreate + onUpdate hooks
- Soft-delete via deleted_at
- On create: autoProvisionPresets(workspace, root) may seed preset AI columns; fire-and-forget recompute over existing records
- On rules_config / formula_config / format_config change: enqueueRecompute → recompute all records for the column
- AI columns (type=‘ai’ or rules_config present) compute via EnrichmentTask (CUSTOM_COLUMN) → Cloud Task → Anthropic Haiku, with anti-prompt-injection guards
Example
{
"data": {
"type": "custom_column",
"id": "7c1f9a02-4d3b-4e21-9a77-2f0c11aa33bc",
"attributes": {
"custom_column_id": "7c1f9a02-4d3b-4e21-9a77-2f0c11aa33bc",
"root": "companies",
"name": "Risk level",
"field_key": "risk_level",
"type": "single_select",
"position": 3,
"icon": "shield-alert",
"rules_config": "{\"prompt\":\"Classify the company risk as low, medium, or high based on its industry and country.\"}",
"formula_config": null,
"format_config": "{\"options\":[\"low\",\"medium\",\"high\"]}",
"created_at": "2026-05-20T09:14:00.000Z",
"updated_at": "2026-05-28T11:02:00.000Z",
"deleted_at": null
}
},
"relationships": {
"workspace": {
"data": {
"type": "workspace",
"id": "a1b2c3d4-0000-4000-8000-000000000001"
}
}
}
}
Source: apps/api/src/database/entities/CustomColumn.ts · domain: records / data-views · tier: Infrastructure