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

# PersonEmail

> PersonEmail is the pivot relation that links a People record to an Email address within the financial graph

PersonEmail is the pivot relation that links a People record to an Email address within the financial graph. It carries metadata about the association — whether the address is the person's primary contact, whether it has been verified, and a label classifying its context (work, personal, other). A single person may have multiple PersonEmail rows; at most one may carry `is_primary = true` per person (enforced by a partial unique index). The entity is workspace-scoped indirectly through the `People` side and is written exclusively by the connector-sync and enrichment pipelines.

| Naming                          | Value                             |
| ------------------------------- | --------------------------------- |
| Object                          | PersonEmail                       |
| Resource type (JSON:API `type`) | `person_email`                    |
| Collection / records root       | — <sub>(not a records root)</sub> |
| REST base                       | `/v1/person-emails`               |
| Entity class                    | `PersonEmail`                     |

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

## Data model

### Attributes

| Field       | Type                                                                         | Required | Constraints                                                                                                                              | Allowed values                  | Description                                                                                                                                                                                                                                                                                            |
| ----------- | ---------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| is\_primary | boolean                                                                      | ⚪ No     | DEFAULT false; partial unique index uniq\_person\_emails\_primary\_person enforces at-most-one primary per person among non-deleted rows | true \| false                   | Whether this email address is the person's primary contact address. At most one PersonEmail per person may have is\_primary = true while deleted\_at IS NULL (enforced by partial unique index uniq\_person\_emails\_primary\_person on person\_pk WHERE deleted\_at IS NULL AND is\_primary IS TRUE). |
| is\_verify  | boolean                                                                      | ⚪ No     | DEFAULT false                                                                                                                            | true \| false                   | Whether the email address has been verified for this person. Set by the enrichment or connector-sync pipeline; not validated via a user-facing flow.                                                                                                                                                   |
| label       | 🔒 system — PersonEmailLabelEnum (native PG enum person\_email\_label\_enum) | ✅ Yes    | DEFAULT 'other'; native enum person\_email\_label\_enum — stored values are the enum VALUE strings                                       | 'work' \| 'personal' \| 'other' | Classifies the context of this email address for the person. Stored as a native PostgreSQL enum introduced in Migration20251204160141.                                                                                                                                                                 |
| created\_at | 🔒 system — Date (timestamptz)                                               | ✅ Yes    | NOT NULL; set on insert via onCreate: () => new Date()                                                                                   | —                               | Timestamp when the pivot row was created. Set by the MikroORM onCreate hook; never updated.                                                                                                                                                                                                            |
| deleted\_at | Date \| null (timestamptz)                                                   | ⚪ No     | NULLABLE; no default (equivalent to null)                                                                                                | —                               | Soft-delete timestamp. Null when the row is active. All queries must filter deleted\_at IS NULL. The partial index idx\_person\_emails\_person and the primary-person uniqueness index both scope to deleted\_at IS NULL.                                                                              |

### Relationships

| Name   | Type               | Required | Description                                                                                                                                                                                                                                                                 |
| ------ | ------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| person | to-one (ManyToOne) | ✅ Yes    | The People record that owns this email address. Foreign key person\_pk references core\_api.peoples(pk) ON UPDATE CASCADE. An index idx\_person\_emails\_person covers person\_pk WHERE deleted\_at IS NULL for reverse-traversal hot-path queries.                         |
| email  | to-one (ManyToOne) | ✅ Yes    | The Email atomic record containing the address string. Foreign key email\_pk references core\_api.emails(pk) ON UPDATE CASCADE. An index idx\_person\_emails\_email covers the email\_pk column to support the Hasura emails → person\_emails array relationship traversal. |

### System-computed

* created\_at — set on insert via MikroORM onCreate hook; never updated (no updated\_at column on this entity)
* deleted\_at — soft-delete; set to current timestamp by the pipeline or service that removes the association; queries must always predicate deleted\_at IS NULL
* is\_primary uniqueness — enforced by partial unique index uniq\_person\_emails\_primary\_person (person\_pk) WHERE deleted\_at IS NULL AND is\_primary IS TRUE; the pipeline is responsible for demoting any prior primary before promoting a new one
* label default — MikroORM entity-level default PersonEmailLabelEnum.OTHER ('other') applied at construction; mirrored by database DEFAULT 'other' set in Migration20251204160141
* is\_primary / is\_verify defaults — entity-level TypeScript defaults (false) mirrored by database DEFAULT false set in Migration20251204160141
* No UUID public identifier — PersonEmail has no \*\_id UUID column; it is not directly addressable via the public API as a standalone resource; it is always accessed through its parent People or Email relationship

## Example

```json theme={null}
{
  "data": {
    "type": "person_email",
    "id": null,
    "attributes": {
      "is_primary": true,
      "is_verify": false,
      "label": "work",
      "created_at": "2025-11-14T09:22:07.000Z",
      "deleted_at": null
    },
    "relationships": {
      "person": {
        "data": { "type": "people", "id": "7e4c2f91-3b8a-4d56-9f1e-bc23047a8e12" }
      },
      "email": {
        "data": { "type": "email", "id": "a1d0c29b-5e3f-4812-8b7a-fc901234abcd" }
      }
    }
  }
}
```

<sub>Source: `/Users/maximechampoux/platform/apps/api/src/database/entities/PersonEmail.ts` · domain: financial-graph · tier: Supporting</sub>
