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

# EnrichmentTask

> EnrichmentTask is the durable work-item record for Well's asynchronous enrichment pipeline

EnrichmentTask is the durable work-item record for Well's asynchronous enrichment pipeline. Each row represents one unit of background AI or data-processing work — logo resolution, AI company/people/invoice extraction, OCR, bank-sync reconciliation, provider scoring, custom column compute, field rule evaluation, or monthly invoice closure — targeted at an arbitrary entity identified by the polymorphic (`entity_type`, `entity_id`) pair. Tasks are scoped to a `Workspace`, can be grouped into a `batch_id` (one Magic-button press), and support parent/subtask nesting via a self-referencing `parent_task` relationship. The enrichment pipeline writes and advances all lifecycle states; users and operators observe tasks read-only.

| Naming                          | Value                             |
| ------------------------------- | --------------------------------- |
| Object                          | EnrichmentTask                    |
| Resource type (JSON:API `type`) | `enrichment_task`                 |
| Collection / records root       | — <sub>(not a records root)</sub> |
| REST base                       | `/v1/enrichment-tasks`            |
| Entity class                    | `EnrichmentTask`                  |

<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/enrichment-tasks`         | 🟡 Planned |
| Retrieve  | `GET /v1/enrichment-tasks/{id}`    | 🟡 Planned |
| Create    | `POST /v1/enrichment-tasks`        | 🟡 Planned |
| Update    | `PATCH /v1/enrichment-tasks/{id}`  | 🟡 Planned |
| Delete    | `DELETE /v1/enrichment-tasks/{id}` | 🟡 Planned |

## Data model

### Attributes

| Field                | Type                                                                                                         | Required | Constraints                                                                                                                                                                                                                                                                          | Allowed values                                                                                                                                                                                                        | Description                                                                                                                                                                                                                                                                         |
| -------------------- | ------------------------------------------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| enrichment\_task\_id | UUID (🔒 system)                                                                                             | ✅ Yes    | UNIQUE                                                                                                                                                                                                                                                                               | —                                                                                                                                                                                                                     | Public stable identifier. Auto-generated by `gen_random_uuid()` at insert. This is the `id` exposed in JSON:API responses; the internal `pk` is never surfaced.                                                                                                                     |
| entity\_type         | string (varchar 100)                                                                                         | ✅ Yes    | max 100 chars; NOT NULL; composite index with entity\_id (`enrichment_tasks_entity_idx`)                                                                                                                                                                                             | —                                                                                                                                                                                                                     | Polymorphic discriminator identifying the kind of entity this task targets (e.g. `company`, `person`, `invoice`, `document`, `transaction`). Pairs with `entity_id` to form the generic entity reference introduced in Migration20260323100000 to replace per-type FK columns.      |
| entity\_id           | string (varchar 255)                                                                                         | ✅ Yes    | max 255 chars; NOT NULL; composite index with entity\_type; partial unique index on (`entity_type`, `entity_id`, `enrichment_type`) WHERE `status = 'pending' AND deleted_at IS NULL AND enrichment_type = 'monthly_close'` enforces one active monthly\_close task per target month | —                                                                                                                                                                                                                     | Public UUID of the target entity (the `*_id` column of the referenced row, e.g. `company_id`, `person_id`, `invoice_id`). Stored as a string to support multiple entity types without per-type FK constraints. Composite index with `entity_type`.                                  |
| status               | enum (🔒 system) — native Postgres type `enrichment_task_status_enum`                                        | ✅ Yes    | DEFAULT 'pending'; NOT NULL                                                                                                                                                                                                                                                          | pending \| processing \| completed \| awaiting\_approval \| failed \| rejected                                                                                                                                        | Lifecycle state of the enrichment task. Default `pending`. Transitions are driven exclusively by the enrichment pipeline workers; users cannot write this field.                                                                                                                    |
| enrichment\_type     | string (text) — backed by Postgres type `enrichment_type_enum` historically but stored as text on the column | ✅ Yes    | NOT NULL                                                                                                                                                                                                                                                                             | logo \| ai\_company \| ai\_people \| ai\_invoice \| ocr\_extract \| reconcile \| provider\_score \| document\_reconciliation\_backfill \| monthly\_close \| monthly\_close\_backfill \| custom\_column \| field\_rule | Identifies the enrichment worker that should process this task. Determines which Cloud Tasks handler is dispatched. See `EnrichmentTypeEnum` for the full controlled vocabulary.                                                                                                    |
| input                | jsonb                                                                                                        | ⚪ No     | nullable                                                                                                                                                                                                                                                                             | —                                                                                                                                                                                                                     | Worker input payload. Shape is worker-specific. For `monthly_close` the dedup key is `input-&gt;&gt;'record_id'` (month label); a JSONB expression partial index (`idx_enrichment_tasks_input_record_id`) covers lookups on that path within a workspace + status window.           |
| output               | jsonb                                                                                                        | ⚪ No     | nullable                                                                                                                                                                                                                                                                             | —                                                                                                                                                                                                                     | Worker output payload written on task completion. Shape is worker-specific. For `monthly_close_backfill`, holds aggregate fan-out counts and request parameters.                                                                                                                    |
| target\_fields       | jsonb (string\[])                                                                                            | ⚪ No     | nullable                                                                                                                                                                                                                                                                             | —                                                                                                                                                                                                                     | Optional list of field names the enrichment worker should populate or re-evaluate. Used by `custom_column` and `field_rule` workers to scope work to a subset of columns.                                                                                                           |
| error                | text                                                                                                         | ⚪ No     | nullable                                                                                                                                                                                                                                                                             | —                                                                                                                                                                                                                     | Error message or stack trace written by the worker when the task transitions to `failed`. Null on success.                                                                                                                                                                          |
| source\_channel      | enum — native Postgres type `source_channel_enum`                                                            | ⚪ No     | nullable                                                                                                                                                                                                                                                                             | company\_create \| person\_create \| document\_upload \| ocr\_completion \| bank\_sync \| email\_import \| mcp\_hub \| cell\_edit \| manual                                                                           | Records which product surface triggered the task. Used for attribution and observability. Added in Migration20260319120000.                                                                                                                                                         |
| input\_hash          | text                                                                                                         | ⚪ No     | nullable; index `enrichment_tasks_input_hash_idx`                                                                                                                                                                                                                                    | —                                                                                                                                                                                                                     | Deduplication fingerprint of the `input` payload. Allows workers to detect duplicate enqueues with identical inputs and skip redundant work. Added in Migration20260319120000.                                                                                                      |
| description          | text                                                                                                         | ⚪ No     | nullable                                                                                                                                                                                                                                                                             | —                                                                                                                                                                                                                     | Human-readable markdown summary of the enrichment task, populated by the worker or the pipeline orchestrator for display in the UI. Added in Migration20260327100000.                                                                                                               |
| batch\_id            | UUID                                                                                                         | ⚪ No     | nullable; index `enrichment_tasks_batch_id_idx`; composite index `idx_enrichment_tasks_batch_status` on (batch\_id, status)                                                                                                                                                          | —                                                                                                                                                                                                                     | Groups tasks triggered by a single user action (Magic button press). All tasks sharing a `batch_id` were enqueued together and can be tracked collectively. Index `idx_enrichment_tasks_batch_status` covers hot-path batch completion detection. Added in Migration20260327100000. |
| created\_at          | timestamptz (🔒 system)                                                                                      | ✅ Yes    | NOT NULL; set once on insert                                                                                                                                                                                                                                                         | —                                                                                                                                                                                                                     | Row creation timestamp set by MikroORM `onCreate` hook. Not writable after insert.                                                                                                                                                                                                  |
| updated\_at          | timestamptz (🔒 system)                                                                                      | ⚪ No     | nullable; updated on every write                                                                                                                                                                                                                                                     | —                                                                                                                                                                                                                     | Last modification timestamp, maintained automatically by MikroORM `onUpdate` hook on every flush.                                                                                                                                                                                   |
| deleted\_at          | timestamptz                                                                                                  | ⚪ No     | nullable                                                                                                                                                                                                                                                                             | —                                                                                                                                                                                                                     | Soft-delete timestamp. When set the row is logically deleted and filtered out of standard queries. The partial unique index on `monthly_close` tasks is scoped to `deleted_at IS NULL`.                                                                                             |
| completed\_at        | timestamptz                                                                                                  | ⚪ No     | nullable                                                                                                                                                                                                                                                                             | —                                                                                                                                                                                                                     | Timestamp written by the worker when the task reaches `completed`, `failed`, or `rejected`. Distinct from `updated_at` to allow precise pipeline latency measurement.                                                                                                               |

### Relationships

| Name         | Type                                  | Required | Description                                                                                                                                                                                                                                                                                                                         |
| ------------ | ------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| workspace    | to-one (ManyToOne)                    | ✅ Yes    | The workspace that owns this enrichment task. All task queries are tenant-scoped via this relationship. `deleteRule: cascade` — deleting a workspace removes all its tasks. FK column `workspace_pk`.                                                                                                                               |
| parent\_task | to-one (ManyToOne, self-referencing)  | ⚪ No     | Optional reference to a parent `EnrichmentTask`. Used by the Monthly Invoice Closure pipeline to link per-counterparty sub-tasks to their macro parent task. FK column `parent_task_pk`. `deleteRule: set null` — deleting a parent task nullifies the FK on children without cascading deletion. Added in Migration20260327100000. |
| subtasks     | to-many (OneToMany, self-referencing) | —        | Inverse collection of child `EnrichmentTask` rows that reference this task as their `parent_task`. Populated for macro tasks in the Monthly Invoice Closure pipeline. Mapped by `parent_task` on the child side.                                                                                                                    |

### System-computed

* enrichment\_task\_id — auto-generated by gen\_random\_uuid() Postgres default at INSERT; never set by application code
* created\_at — set by MikroORM onCreate hook; never writable after insert
* updated\_at — set and maintained by MikroORM onUpdate hook on every flush
* deleted\_at — soft-delete; set by the pipeline or admin tooling, never by user PATCH
* status — default 'pending' at creation; all state transitions (pending → processing → completed / failed / rejected / awaiting\_approval) are driven exclusively by enrichment pipeline workers via Cloud Tasks handlers
* input\_hash — computed by the enqueuing service as a fingerprint of the input payload for dedup detection; not computed by the database
* batch\_id — assigned at enqueue time by the orchestrator when multiple tasks are triggered together (Magic button); not user-assignable
* completed\_at — written by the worker on task terminal state; not set by application business logic outside the worker
* entity\_type / entity\_id — set at enqueue time from the triggering entity's public UUID; the generic polymorphic reference replaced per-type FK columns (company\_pk, person\_pk, document\_pk, invoice\_pk, transaction\_pk) in Migration20260323100000
* subtasks collection — populated by ORM from the OneToMany inverse of parent\_task; not a stored column

## Example

```json theme={null}
{
  "data": {
    "type": "enrichment_task",
    "id": "c3a1f9e2-4b7d-4e2a-8f1c-9a0b3d5e7f21",
    "attributes": {
      "enrichment_task_id": "c3a1f9e2-4b7d-4e2a-8f1c-9a0b3d5e7f21",
      "entity_type": "company",
      "entity_id": "a1b2c3d4-0000-0000-0000-000000000001",
      "status": "completed",
      "enrichment_type": "ai_company",
      "input": { "company_id": "a1b2c3d4-0000-0000-0000-000000000001" },
      "output": { "domain": "acme.com", "registered_name": "Acme Corp" },
      "target_fields": ["domain", "registered_name"],
      "error": null,
      "source_channel": "company_create",
      "input_hash": "sha256:abc123",
      "description": null,
      "batch_id": "f7e6d5c4-3b2a-1908-7654-321098fedcba",
      "created_at": "2026-05-15T10:30:00.000Z",
      "updated_at": "2026-05-15T10:31:05.000Z",
      "deleted_at": null,
      "completed_at": "2026-05-15T10:31:05.000Z"
    },
    "relationships": {
      "workspace": {
        "data": { "type": "workspace", "id": "ws-uuid-0001" }
      },
      "parent_task": {
        "data": null
      }
    }
  }
}
```

<sub>Source: `apps/api/src/database/entities/EnrichmentTask.ts` · domain: ingestion · tier: Infrastructure</sub>
