Skip to main content

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.

Phone is a shared atomic resource representing a single telephone number stored in its canonical decomposed form: ITU-T country-calling-code, national-number string, and the derived E.164 number. It is linked to People and Company records through pivot entities (PersonPhone, CompanyPhone) that carry relationship-level metadata such as primary/verified status and a label. A Phone always belongs to a workspace via a nullable integer FK (workspace_pk) added in Migration20260119180000 and is soft-deletable. It is exposed as a records root named “phones” in the data-views pipeline with composite columns resolving linked companies and people.
NamingValue
ObjectPhone
Resource type (JSON:API type)phone
Collection / records rootphones
REST base/v1/phones
Entity classPhone

API operations

OperationMethod & pathStatus
ListGET /v1/phones✅ Implemented
List (nested)GET /v1/people/{id}/phones🟡 Planned
RetrieveGET /v1/phones/{id}✅ Implemented
Create (nested)POST /v1/people/{id}/phones✅ Implemented
UpdatePATCH /v1/phones/{id}🟡 Planned
Delete (nested)DELETE /v1/people/{id}/phones/{subId}✅ Implemented

Data model

Attributes

FieldTypeRequiredConstraintsAllowed valuesDescription
phone_idstring, UUID, 🔒 system✅ Yesunique; generated by gen_random_uuid() on INSERTPublic stable identifier for the phone number. Used in all API responses and cross-resource references. The internal pk is never exposed.
country_codeinteger✅ YesNOT NULLAny valid ITU-T calling code (e.g. 1, 33, 44, 49)The international dialing prefix without the leading ’+’. For example France = 33, US = 1, UK = 44.
national_numberstring✅ Yesvarchar(255); NOT NULLThe national (subscriber) portion of the phone number, without the country code prefix and without leading zeros stripped. Stored as a string to preserve leading zeros for countries that require them.
e164_numberstring✅ Yesvarchar(255); NOT NULLThe fully-qualified E.164 representation of the number, including the leading ’+’ and country code. This is the canonical machine-readable form used for display, deduplication, and connector sync matching.
created_atdatetime, 🔒 system✅ YesNOT NULL; set once on INSERT via onCreate lifecycle hookTimestamp at which the Phone row was created. Immutable after creation.
updated_atdatetime, 🔒 system⚪ Nonullable; set on INSERT and updated on every UPDATE via onUpdate lifecycle hookTimestamp of the last modification to the Phone row. Null if the row has never been updated after creation.
deleted_atdatetime⚪ Nonullable; null = active recordSoft-delete timestamp. When set, the phone number is considered deleted and all queries must filter deleted_at IS NULL. Hard-deletes are not used.

Relationships

NameTypeRequiredDescription
workspaceto-one (workspace)⚪ No (nullable)The workspace that owns this phone number. @ManyToOne(() => Workspace, { nullable: true }). The DB column is workspace_pk (int FK → core_api.workspaces.pk, ON DELETE SET NULL), added by Migration20260119180000. Provides tenant isolation for Hasura RLS filtering.
person_phonesto-many (person_phone)Pivot entities linking this phone to one or more People records. Each PersonPhone carries is_primary (with a partial-unique constraint: only one primary per person while deleted_at IS NULL), is_verify, label (PersonPhoneLabelEnum: mobile | work | personal | other), and created_at. Reverse-traversal index idx_person_phones_phone is on phone_pk.
company_phonesto-many (company_phone)Pivot entities linking this phone to one or more Company records. Each CompanyPhone carries is_primary (partial-unique: one primary per company while deleted_at IS NULL), is_verify, label (free-text string), and created_at. Bridge-table indexes: idx_company_phones_phone (phone_pk), idx_company_phones_company_deleted (company_pk, deleted_at).

System-computed

  • phone_id is generated by gen_random_uuid() at the database level on INSERT and carries a UNIQUE constraint. It is the public API identifier; the internal pk (serial int) is never exposed.
  • created_at is set via MikroORM onCreate lifecycle hook (new Date()) and is immutable thereafter.
  • updated_at is set on both INSERT (onCreate) and every UPDATE (onUpdate) via lifecycle hooks.
  • deleted_at is null by default. Setting it to a non-null timestamp performs a soft-delete. All reads must include a deleted_at IS NULL predicate. Hard-deletes are not used for Phone rows.
  • workspace FK column in the DB is workspace_pk (int, nullable FK → core_api.workspaces.pk, ON DELETE SET NULL), added by Migration20260119180000. Pre-migration rows have workspace_pk = NULL. The entity declares the relation nullable: true. There is no UUID workspace_id column on the phones table.
  • The PersonPhone pivot enforces a partial unique index (uniq_person_phones_primary_person) so that at most one PersonPhone per person_pk has is_primary = TRUE while deleted_at IS NULL.
  • The CompanyPhone pivot enforces a parallel partial unique index (uniq_company_phones_primary_company) so that at most one CompanyPhone per company_pk has is_primary = TRUE while deleted_at IS NULL.
  • In the data-views pipeline, the phones root exposes two composite columns: composite_companies_list (display_type: relation_list, source_fields: company_phones.company.company_id + company_phones.company.name) and composite_people_list (display_type: relation_list, source_fields: person_phones.people.person_id + person_phones.people.full_name). These are defined in composites.yml under the phones root.
  • On company and person records roots, composite_phones_list composites surface linked phone numbers (source_fields: .phone.phone_id + .phone.e164_number) for display in the records table.

Example

{
  "data": {
    "type": "phone",
    "id": "a3f7c291-84e2-4d55-9fc3-b8120e4a7301",
    "attributes": {
      "phone_id": "a3f7c291-84e2-4d55-9fc3-b8120e4a7301",
      "country_code": 33,
      "national_number": "612345678",
      "e164_number": "+33612345678",
      "created_at": "2025-09-14T10:22:00.000Z",
      "updated_at": "2026-01-07T08:05:00.000Z",
      "deleted_at": null
    },
    "relationships": {
      "workspace": {
        "data": { "type": "workspace", "id": "f1a2b3c4-0000-0000-0000-000000000001" }
      },
      "person_phones": {
        "data": [
          { "type": "person_phone", "id": "pivot-pk-91" }
        ]
      },
      "company_phones": {
        "data": []
      }
    }
  }
}
Source: apps/api/src/database/entities/Phone.ts · domain: financial-graph · tier: Supporting