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

# The Object object

> The tables in your workspace, and the properties that define their columns.

An object is a table: Contacts, Companies, Deals, or anything your workspace
defines. Its **properties** are its columns. Read an object before writing to it:
the property types decide what values [records](/dev/api-reference/records) will
accept.

<ResponseExample>
  ```json The Object object theme={null}
  {
    "id": "obj_3Ab9xK2mQ7",
    "key": "contacts",
    "name": "Contacts",
    "description": "People we talk to",
    "icon": "user",
    "color": "blue",
    "system": false,
    "primaryPropertyId": "prop_5Bc0xJ1kP4",
    "properties": [
      { "id": "prop_5Bc0xJ1kP4", "key": "full_name", "type": "text", "…": "…" },
      {
        "id": "prop_7Cd1yK9lQ2",
        "key": "stage",
        "type": "select",
        "options": [
          { "id": "opt_7Fd2yL8nR1", "value": "Qualified", "description": null, "color": "green", "seq": 0 },
          { "id": "opt_8Ge3zM9oS2", "value": "Won", "description": null, "color": "blue", "seq": 1 }
        ],
        "…": "…"
      }
    ]
  }
  ```
</ResponseExample>

## Attributes

<ResponseField name="id" type="string">
  Unique identifier, prefixed `obj_`.
</ResponseField>

<ResponseField name="key" type="string">
  The stable, URL-safe identifier, `contacts`. Usable anywhere an endpoint takes
  an `{object}` segment, and what a record's `object` field reports.
</ResponseField>

<ResponseField name="name" type="string">
  The display name shown in the app.
</ResponseField>

<ResponseField name="description" type="string | null">
  Free-text description.
</ResponseField>

<ResponseField name="icon" type="string | null">
  Icon name used in the app.
</ResponseField>

<ResponseField name="color" type="string | null">
  The object's accent color.
</ResponseField>

<ResponseField name="system" type="boolean">
  `true` for objects Custral ships and maintains. System objects can be extended
  with your own properties but not deleted.
</ResponseField>

<ResponseField name="primaryPropertyId" type="string">
  The **primary property**. The one whose value becomes a record's `name`.
</ResponseField>

<ResponseField name="properties" type="array">
  The object's columns (see the Property object below). **Present only when you
  retrieve a single object**. The list response omits it to stay lean.

  <Expandable title="property attributes">
    <ResponseField name="id" type="string">Unique identifier, prefixed `prop_`.</ResponseField>
    <ResponseField name="key" type="string">The stable identifier, **what a record's `fields` map is keyed by**, and what you send when writing.</ResponseField>
    <ResponseField name="name" type="string">The display name. Also accepted (case-insensitively) when writing.</ResponseField>
    <ResponseField name="type" type="string">What kind of value this property holds, `text`, `number`, `select`, `relation`, … See [How the schema works](/dev/api-reference/schema).</ResponseField>
    <ResponseField name="version" type="integer">Increments when the definition changes materially. Integrations don't need to track it.</ResponseField>
    <ResponseField name="isRequired" type="boolean">Whether the app requires a value. The API does not reject a record that omits it.</ResponseField>
    <ResponseField name="isFilterable" type="boolean">Whether the property is indexed for filtering and sorting.</ResponseField>
    <ResponseField name="isHidden" type="boolean">Whether it's hidden in the app's default views. Still readable + writable via the API.</ResponseField>
    <ResponseField name="isLocked" type="boolean">Whether the property's definition is protected from edits.</ResponseField>
    <ResponseField name="seq" type="integer">Display order within the object.</ResponseField>
    <ResponseField name="config" type="object">Type-specific settings: a `currency`'s code, a `select`'s `isMultiSelect` flag, a `formula`'s expression. The choices themselves are in `options`, not here.</ResponseField>

    <ResponseField name="options" type="array">
      The property's choices, **present only on `select`, `status` and multi-select properties that have any**. Absent on every other type, and absent when none were loaded.

      A record stores the option's **id**, not its label, so a `select` field reads back as `["opt_7Fd2yL8nR1"]`. Use this list to render that as a label, and to offer the values a write may set. Writes accept either the id or the label, matched case-insensitively.

      <Expandable title="option attributes">
        <ResponseField name="id" type="string">Unique identifier, prefixed `opt_`. This is what a record's field value holds.</ResponseField>
        <ResponseField name="value" type="string">The label, e.g. `Qualified`. Unique within the property, not across the workspace.</ResponseField>
        <ResponseField name="description" type="string | null">Optional explanatory text.</ResponseField>
        <ResponseField name="color" type="string | null">The chip color the app renders.</ResponseField>
        <ResponseField name="seq" type="integer">Display order within the property. The list is returned in this order.</ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<Note>
  The retrieve endpoint takes the object's **id or its `key`**, the same as the
  record endpoints. `GET /v1/objects/contacts` and
  `GET /v1/objects/obj_3Ab9xK2mQ7` return the same object.
</Note>


## Related topics

- [Spreadsheet](/blocks/embedded/object/spreadsheet.md)
- [List objects](/api-reference/objects/list-objects.md)
- [Retrieve an object](/api-reference/objects/retrieve-an-object.md)
- [Standard Objects](/data/objects/standard-objects.md)
- [Object Views](/data/objects/views.md)
