OXYGENOxygen/ Docs
Data

Relations

Relation columns link CRM records across tables — built-in and user-defined relationships, edges, and cardinality.

A relation column links records in one CRM object table to records in another. Unlike other columns, the linked values do not live in the row: each link is an edge stored in the tenant database with provenance (api, cli, tool, workflow, system), timestamps, and archive state. The relation column is the anchor that renders those edges on the table grid and record page.

Relations are CRM object semantics. They exist on object-backed tables (companies, people, deals, and your custom objects) — a plain working table has no relation columns until you promote it to a CRM object.

Built-in relationships

oxygen crm setup creates the standard objects with their relationships already defined:

SourceSlugTargetInverseCardinality
companiesteampeoplecompanyone company : many people
dealscompanycompaniesdealsmany deals : one company
dealsprimary_contactpeopledealsmany deals : one person
dealsstakeholderspeopledeals_involvedmany : many, with a per-edge role

oxygen crm objects describe <object> --json lists every relationship an object participates in, both directions.

Defining your own relationship

Define a relationship from a custom object to any object (custom or standard). This creates the relation column on the source and registers the relationship definition; a custom target with --inverse-slug gets the inverse relation column too.

# Preview first (default is dry-run)
oxygen crm relationships define projects client \
  --target-object companies \
  --cardinality many_to_one \
  --inverse-slug projects \
  --json

# Apply
oxygen crm relationships define projects client \
  --target-object companies \
  --cardinality many_to_one \
  --inverse-slug projects \
  --live --json

MCP: oxygen_crm_relationship_define with { object, slug, target_object, cardinality?, inverse_slug?, mode }.

Rules:

  • The source must be a custom object — standard object schemas (companies/people/deals) are managed by crm setup and cannot grow new relation columns. Point the relationship at the standard object instead and use the inverse slug to navigate back.
  • The relationship slug doubles as the relation column key on the source table (snake_case).
  • Definitions are free internal schema writes — no credits.
  • Self-relationships (projectsprojects) are allowed with distinct forward and inverse slugs.

Cardinality

--cardinality is read source:target, and controls how many active edges each record may hold. Writing an edge beyond a one side archives the previous edge (visible in edge history, not deleted).

ValueMeaning
one_to_oneEach source record links one target, each target one source
one_to_manyEach source record links many targets; each target links back to one source
many_to_oneEach source record links one target; a target can be linked by many sources
many_to_manyNo limit on either side (default)

Linking records

Once a relationship is defined (built-in or custom), link records with an edge write:

oxygen crm relationships upsert projects <row_id> \
  --relationship client \
  --target-row-id <company_row_id> \
  --live --json

Defaults to dry-run; the preview shows which edges would be created and which would be archived by cardinality. MCP: oxygen_crm_relationship_upsert.

Inspect the result:

oxygen crm records get projects <row_id> --json   # relationships.outbound / .inbound
oxygen crm objects describe projects --json        # definitions on the object

On the web, the record page renders each relation column with a search-picker; edges also appear on the linked record's side.

Plain tables

Working tables (imports, TAM builds, scratch lists) don't carry relations. To relate their rows, promote the table onto a CRM object first, then define the relationship on that object:

oxygen tables promote <table-id> --object <object> --dry-run --json
  • Columns — the other column kinds.
  • Tables — raw, object-backed, and list-backed tables.
  • Approvals — dry-run/live doctrine.

On this page