> ## Documentation Index
> Fetch the complete documentation index at: https://docs.attio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Record reference

> Relationships and one-way links between records

Record reference attributes are one of the most useful types of attribute. They allow pointing to other records of the same object, or records of other objects. When combined with features such as drill-down filters, it becomes possible to deeply relate the various parts of your data model.

By default, all of the standard objects have at least one record reference:

* Company has `team` (people), `associated_deals` (deals) and `associated_workspaces` (workspaces)
* Person has `company` (company), `associated_deals`(deals) and `associated_users` (users)
* Deal has `associated_people` (people) and `associated_company` (company)
* User has `person` (person) and `workspace` (workspace)
* Workspace has `users` (users) and `company` (company)

### A note about relationship attributes

All of the example attributes above are also relationship attributes.

[Relationship attributes](https://attio.com/help/reference/workspace/attributes#relationship-attributes) describe a relationship between two objects, which appear as a pair of record reference attributes, one on each object. Updating an attribute value on either of the attributes automatically updates the other attribute, which means you don't need to explicitly update both. For example, adding a person to a company by updating the company `team` property, will also update the `company` property on that person.

Currently, you will be able to see relationship attributes alongside other non-relationship record reference attributes in the API. The attribute type is still marked as `record-reference`, but there is an additional property, `relationship`, that you can use to distinguish these.

If the attribute is also a relationship attribute, the `relationship` property will be an object containing an `id` property. In the example below, our company's `team` attribute has a relationship with the person's `company` attribute:

<CodeGroup>
  ```jsonc Example "team" attribute on a company theme={"system"}
  {
    "id": {
      "workspace_id": "14beef7a-99f7-4534-a87e-70b564330a4c",
      "object_id": "7c430b6d-fa5b-48c6-bfa7-9520c088c7bc",
      "attribute_id": "8468fb8b-52f4-4a7f-ae42-3a4bed9782e4"
    },
    "title": "Team",
    "api_slug": "team",
    "type": "record-reference",
    "relationship": {
      "id": {
        "workspace_id": "14beef7a-99f7-4534-a87e-70b564330a4c",
        "object_id": "4e71c40b-7d35-463c-afcb-e339cfd6dbd1", // Person object
        "attribute_id": "41252299-f8c7-4b5e-99c9-4ff8321d2f96" // "Company" attribute on Person object
      }
    }
  }
  ```
</CodeGroup>

If the record reference attribute is not a relationship attribute, the `relationship` property will be set to `null`.

In the web application, when setting up a relationship, the user specifies whether the relationship is many-to-many, many-to-one, one-to-many or one-to-one. It is possible to discern this relationship by looking at the `is_multiselect` property on each attribute: if `true`, this attribute is a "many", if `false` it is a "one".

Unfortunately, at present it is not possible to create relationship attributes using the API; they can only be created in the web application and then used in the API.

### Configuration

Record references are usually constrained to referencing a specific object. For example, you can't specify a deal for the company `team` attribute. This is accomplished with the configuration property `allowed_object_ids` which is an array of object IDs (slugs are supported when writing this property):

<CodeGroup>
  ```http Create "owner" attribute which only supports People theme={"system"}
  POST /v2/objects/:object/attributes HTTP/1.1
  Authorization: Bearer <<oauth2>>
  Content-Type: application/json

  {
    "title": "Owner",
    "api_slug": "owner",
    "type": "record-reference",
    "config": {
      "record_reference": {
        "allowed_objects": ["person"]
      }
    }
  }

  ```
</CodeGroup>

In responses from the API, this appears as `allowed_object_ids`, like so:

<CodeGroup>
  ```jsonc Attribute definition response for "team" attribute theme={"system"}
  {
    "id": {
      "workspace_id": "14beef7a-99f7-4534-a87e-70b564330a4c",
      "object_id": "7c430b6d-fa5b-48c6-bfa7-9520c088c7bc",
      "attribute_id": "8468fb8b-52f4-4a7f-ae42-3a4bed9782e4"
    },
    "title": "Team",
    "api_slug": "team",
    "type": "record-reference",
    "config": {
      "record_reference": {
        "allowed_object_ids": ["4e71c40b-7d35-463c-afcb-e339cfd6dbd1"]
      }
    }
  }
  ```
</CodeGroup>

### Reading values

Record reference values have two properties, `target_object` (the `api_slug` representing what kind of object it is) and `target_record_id` (the ID of the Record).

<CodeGroup>
  ```jsonc A reference to person@company.com theme={"system"}
  {
    "active_from": "2023-04-03T15:21:06.447000000Z",
    "active_until": null,
    "created_by_actor": {},
    "attribute_type": "record-reference",
    "target_object": "people",
    "target_record_id": "891dcbfc-9141-415d-9b2a-2238a6cc012d"
  }
  ```
</CodeGroup>

### Writing values

There are multiple ways to write a record reference. Since it's such a common operation, Attio provides special write functionality if the record reference only allows a single object and that object is one of our standard objects:

* If the allowed object is a company, you can use the `domains` attribute.
* If the allowed object is a person, you can use the `email_addresses` attribute.
* If the allowed object is a user, you can use the `user_id` attribute.
* If the allowed object is a workspace, you can use the `workspace_id` attribute.

<CodeGroup>
  ```json Referencing a company theme={"system"}
  {
    "associated_company": [
      {
        "domains": [{"domain": "company.com"}],
        "target_object": "companies"
      }
    ]
  }
  ```

  ```json Referencing a person theme={"system"}
  {
    "team": [
      {
        "email_addresses": [{"email_address": "[email protected]"}],
        "target_object": "people"
      }
    ]
  }
  ```

  ```json Referencing a user theme={"system"}
  {
    "user": [
      {
        "user_id": [{"value": "my-user-id"}],
        "target_object": "users"
      }
    ]
  }
  ```

  ```json Referencing a workspace theme={"system"}
  {
    "workspace": [
      {
        "workspace_id": [{"value": "my-workspace-id"}],
        "target_object": "workspaces"
      }
    ]
  }
  ```
</CodeGroup>

Furthermore, we allow writing to these attributes using string values.

* If the allowed object is a company, string values will be interpreted as a domain.
* If the allowed object is a person, string values will be interpreted as email addresses.
* If the allowed object is a user, string values will be interpreted as `user_id` text values.
* If the allowed object is a workspace, string values will be interpreted as `workspace_id` text values.

<CodeGroup>
  ```json Domain theme={"system"}
  {
    "associated_company": "company.com"
  }
  ```

  ```json Domains theme={"system"}
  {
    "associated_company": ["company.com", "company.net"]
  }
  ```

  ```json Email theme={"system"}
  {
    "team": ["[email protected]"]
  }
  ```

  ```json Email theme={"system"}
  {
    "team": ["[email protected]", "[email protected]"]
  }
  ```

  ```json User theme={"system"}
  {
    "user": "my-user-id"
  }
  ```

  ```json Users theme={"system"}
  {
    "user": ["my-user-id", "another-user-id"]
  }
  ```

  ```json Workspace theme={"system"}
  {
    "workspace": "my-workspace-id"
  }
  ```

  ```json Workspaces theme={"system"}
  {
    "workspace": ["my-workspace-id", "another-workspace-id"]
  }
  ```
</CodeGroup>

If the attribute is multiselect ("many"), you can also pass these as a series of values like so:

It's also possible to write record references using record IDs.

<CodeGroup>
  ```json Using record IDs theme={"system"}
  {
    "associated_company": [
      {
        "target_record_id": "99a03ff3-0435-47da-95cc-76b2caeb4dab",
        "target_object": "companies"
      }
    ]
  }
  ```
</CodeGroup>

Note that the write will fail if the target record does not exist, i.e. you can't create the target record automatically. For example, if you tried to assert a person and referenced a company that did not exist, the request would fail. This means that you need to do your writes in reverse-order, e.g. starting with the company that the person is linked to, then creating the person.

### Filtering

Record reference values can be filtered by `target_object` and `target_record_id` using exact equality matches.

<CodeGroup>
  ```json Find people with a given company theme={"system"}
  {
    "filter": {
      "company": {
        "target_object": "companies",
        "target_record_id": "99a03ff3-0435-47da-95cc-76b2caeb4dab"
      }
    }
  }
  ```

  ```json Find workspaces with a given user theme={"system"}
  {
    "filter": {
      "users": {
        "target_object": "97052eb9-e65e-443f-a297-f2d9a4a7f795",
        "target_record_id": "5e3fb280-007b-495a-a530-9354bde01de1"
      }
    }
  }
  ```
</CodeGroup>

As well as exact equality matches, record reference values also support the `$in` operator.

<CodeGroup>
  ```json Find people where their company's record_id is one of several possible values theme={"system"}
  {
    "filter": {
      "company": {
        "target_object": "companies",
        "target_record_id": {
          "$in": ["3aeb39cd-fed8-524e-94b8-1300549354ac", "8c5cd602-1297-45d2-a99c-14ae091cbac3"]
        }
      }
    }
  }
  ```
</CodeGroup>

Record references are special, because they are also filterable using "paths", also known as "drill-downs". You can filter records based on attributes of the target records. `paths` is an array containing tuples of `(object type, attribute slug or ID)`, while `constraints` are applied to the attribute identified by the final path element.

For example, we could construct a filter like "find me Companies which have an employee named John":

<CodeGroup>
  ```json Companies with an employee named John theme={"system"}
  {
    "filter": {
      "path": [
        ["companies", "team"],
        ["people", "name"]
      ],
      "constraints": {
        "first_name": {"$eq": "John"}
      }
    }
  }
  ```
</CodeGroup>

Here, we're using the `team` attribute on a Company, which is a multi-select record reference to the person record. We then look across at those related `people`, and their `name` attribute values. Finally, since `name` is a [(personal) name](/rest-api/attribute-types/attribute-types-personal-name) attribute, we can query against the `first_name` property.

Paths can be more complex, and even somewhat recursive. For example, if you had a `manager` attribute on the Person object, and it pointed to another Person, you could find people by who their manager's manager's manager was:

<CodeGroup>
  ```json People by their manager's manager's manager theme={"system"}
  {
    "filter": {
      "path": [
        ["people", "manager"],
        ["people", "manager"]
      ],
      "constraints": {
        "target_object": "people",
        "target_record_id": "managers-manager-id"
      }
    }
  }
  ```
</CodeGroup>
