# Metafields

Learn about Metafields; the way you compose, extend, and connect the Object content model in Cosmic.

**What are Metafields?** Metafields are the way to add custom fields to your Objects. They are stored in the Object type and are not stored in the Object. They contain the data model, validation, etc.

**What is Metadata?** Metadata is the data you add to your Objects using the Metafields model. They contain the data values.

## Data model

| Parameter               |                         Required                         |       Type       | Description                                                                                                                                                                                      |
| :---------------------- | :------------------------------------------------------: | :--------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`                  |                         required                         |       Enum       | text, textarea, html-textarea, select, multi-select, select-dropdown, object, objects, file, files, date, radio-buttons, check-boxes, repeater, parent, markdown, json, switch, number, color, emoji                   |
| `title`                 |                         required                         |      String      | Your Metafield title                                                                                                                                                                             |
| `key`                   |                         required                         |      String      | Unique identifier for your Metafield                                                                                                                                                             |
| `value`                 |                          varies                          | Varies by `type` | Metafield value. Property required to be present (empty string ok) except for `repeater` and `parent` (should not be present). See example model below for various value types and requirements. |
| `required`              |                                                          |       Bool       | A value is required                                                                                                                                                                              |
| `unique`                |                                                          |       Bool       | Value must be unique across all Objects of the same type. Applies to top-level text, textarea, number, date, select Metafields (not supported inside Parent or Repeater groups). Localized versions of the same Object are excluded from this check.                   |
| `regex`                 |                                                          |      String      | Restrict the value to match a regular expresssion                                                                                                                                                |
| `regex_message`         |                                                          |      String      | The message displayed when the value fails the regex                                                                                                                                             |
| `minlength`             |                                                          |      Number      | Add minlength to text or textarea Metafields                                                                                                                                                     |
| `maxlength`             |                                                          |      Number      | Add maxlength to text or textarea Metafields                                                                                                                                                     |
| `options`               | Required for `select`, `multi-select`, `radio`, `checkbox` and `switch` | Varies by `type` | Array of `{ "value": "..." }` options for `select`, `multi-select`, `select-dropdown`, radio, and checkbox Metafields. String for switch Metafield with possible values `true,false` and `yes,no`                                                       |
| `children`              |                                                          |      Array       | Array of nested Metafields                                                                                                                                                                       |
| `object_type`           |                                                          |      String      | Valid Object type slug. Applies only to `object` and `objects` Metafield                                                                                                                         |
| `repeater_fields`       |                                                          |      Array       | Array of nested Metafields. Applies only to `repeater` Metafield                                                                                                                                 |
| `media_validation_type` |                                                          |      String      | image, video, audio, application. Applies only to `file` and `files` Metafield                                                                                                                   |
| `show_when`             |                                                          |      Object      | Conditional visibility. Show this field only when a sibling field matches a condition. Format: `{ "key": "field_key", "op": "eq" or "neq" or "exists" or "not_exists", "value": "match_value" }`. Hidden fields skip required validation. The API always stores all fields. Top-level only. |

## Adding and editing Metafields

When adding / editing Metafields to Object types using the API, use the following model for each Metafields type. Any value added to the `value` property is treated as a default value on each newly created Object.
```json
{
  "metafields": [
    {
      "type": "text",
      "title": "Headline",
      "key": "headline",
      "value": "3030 Palo Alto Blvd.",
      "required": true
    },
    {
      "type": "textarea",
      "title": "Basic Text",
      "key": "basic_text",
      "value": "This home is a must see!",
      "required": true
    },
    {
      "type": "html-textarea",
      "title": "Extended Text",
      "key": "extended_text",
      "value": "<p>Some <strong>HTML content</strong> for <em>dramatic</em> effect!</p>"
    },
    {
      "type": "markdown",
      "title": "Markdown Text",
      "key": "markdown_text",
      "value": "# Hello World!"
    },
    {
      "type": "select-dropdown",
      "title": "State",
      "key": "state",
      "value": "California",
      "options": [
        {
          "key": "CA",
          "value": "California"
        },
        {
          "key": "TX",
          "value": "Texas"
        }
      ]
    },
    {
      "type": "select",
      "title": "Category",
      "key": "category",
      "value": "Technology",
      "options": [
        { "value": "Technology" },
        { "value": "Business" },
        { "value": "Design" }
      ]
    },
    {
      "type": "multi-select",
      "title": "Tags",
      "key": "tags",
      "value": ["Technology", "Business"],
      "options": [
        { "value": "Technology" },
        { "value": "Business" },
        { "value": "Design" }
      ]
    },
    {
      "type": "object",
      "title": "Author",
      "key": "author",
      "object_type": "authors",
      "value": "5a4806974fa85fc8a7000002" // Object ID
    },
    {
      "type": "objects",
      "title": "Categories",
      "key": "categories",
      "object_type": "categories",
      "value": ["5a4806974fa85fc8a7000007,5a4806974fa85fc8a7000008"] // Object IDs
    },
    {
      "type": "file",
      "title": "Hero",
      "key": "hero",
      "value": "media-name-property-in-bucket.jpg", // This is the name of your media.
      "media_validation_type": "image"
    },
    {
      "type": "files",
      "title": "Gallery",
      "key": "gallery",
      "value": [
        "gallery-image-1.jpg",
        "gallery-image-2.jpg",
        "gallery-image-3.jpg"
      ] // These are the names of your media.
    },
    {
      "type": "date",
      "title": "Listing Start Date",
      "key": "listing_start_date",
      "value": "2020-10-15"
    },
    {
      "type": "json",
      "title": "JSON Data",
      "key": "json_data",
      "value": {
        "strings": "cheese",
        "arrays": ["Bradbury", "Charles", "Ramono", "the last Jedi", "Liotta"],
        "objects": {
          "bools": true,
          "nestable": true
        }
      }
    },
    {
      "type": "radio-buttons",
      "title": "Deposit Required",
      "key": "deposit_required",
      "value": "The Other",
      "options": [
        {
          "value": "This"
        },
        {
          "value": "That"
        },
        {
          "value": "The Other"
        }
      ]
    },
    {
      "type": "check-boxes",
      "title": "Amenities",
      "key": "amenities",
      "value": ["Pool", "Gym"],
      "options": [
        {
          "value": "Pool"
        },
        {
          "value": "Gym"
        },
        {
          "value": "Landscaping"
        }
      ]
    },
    {
      "type": "switch",
      "title": "This is great",
      "key": "this_is_great",
      "value": true,
      "options": "true,false"
    },
    {
      "type": "color",
      "title": "Color",
      "key": "color",
      "value": "#29abe2"
    },
    {
      "type": "parent", // ! Value is not allowed for parent Metafield !
      "title": "Call Out Section",
      "key": "call_out_section",
      "children": [
        {
          "type": "text",
          "title": "Headline",
          "key": "headline",
          "value": "You're Going to Love it Here!"
        },
        {
          "type": "html-textarea",
          "title": "Section Content",
          "key": "section_content",
          "value": "<p>You are going to <strong>love</strong> it in Cosmic Village. The best place to raise a team!</p>"
        },
        {
          "type": "file",
          "title": "Hero",
          "key": "hero",
          "value": "big-beautiful-image.jpg",
          "media_validation_type": "image"
        }
      ]
    },
    {
      "type": "repeater", // ! Value is not allowed for repeater Metafield !
      "title": "Testimonials",
      "key": "testimonials",
      // Available repeaters
      "repeater_fields": [
        {
          "title": "Name",
          "key": "name",
          "value": "",
          "type": "text",
          "required": false
        },
        {
          "title": "Quote",
          "key": "quote",
          "value": "",
          "type": "text",
          "required": false
        }
      ]
    }
  ]
}

```
### `select` and `multi-select`
```json
{
  "type": "select",
  "title": "Category",
  "key": "category",
  "value": "Technology",
  "options": [
    { "value": "Technology" },
    { "value": "Business" },
    { "value": "Design" }
  ]
}

```
```json
{
  "type": "multi-select",
  "title": "Tags",
  "key": "tags",
  "value": ["Technology", "Business"],
  "options": [
    { "value": "Technology" },
    { "value": "Business" },
    { "value": "Design" }
  ]
}
```

### Metafield Validation

You can use optional validation parameters to make sure editors using the web dashboard enter the correct values.

Reference the [Metafield model](/docs/api/metafields#data-model) to learn more.

| Parameter       | Required | Type   | Description                                                                          |
| --------------- | -------- | ------ | ------------------------------------------------------------------------------------ |
| `required`      |          | Bool   | A value is required                                                                  |
| `unique`        |          | Bool   | Value must be unique per Object type. Applies to top-level text, textarea, number, date, select (not inside Parent or Repeater). Localized versions of the same Object are excluded. |
| `regex`         |          | String | Restrict the value to match a regular expresssion                                    |
| `regex_message` |          | String | The message displayed when the value fails the regex                                 |
| `minlength`     |          | Number | Add minlength to text or textarea Metafields                                         |
| `maxlength`     |          | Number | Add maxlength to text or textarea Metafields                                         |
| `show_when`     |          | Object | Conditional visibility. Show field only when sibling matches condition. See [show_when](#conditional-visibility). |

### Conditional Visibility

Use the `show_when` property to show or hide a Metafield based on another field's value. This is a UI-only feature: the API always stores and returns all Metafield values regardless of visibility state.

```json
{
  "key": "company_name",
  "title": "Company Name",
  "type": "text",
  "required": true,
  "show_when": {
    "key": "contact_type",
    "op": "eq",
    "value": "Business"
  }
}
```
**Operators:**
- `eq` - Field value equals the specified value
- `neq` - Field value does not equal the specified value
- `exists` - Field has any non-empty value
- `not_exists` - Field is empty or not set

When a field is hidden by its `show_when` condition, `required` validation is automatically skipped.

### Example Metafields with validation

```json
{
  "title": "Users",
  "singular": "User",
  "slug": "users",
  "metafields": [
    {
      "key": "first_name",
      "title": "First Name",
      "type": "text",
      "required": true,
      "minlength": 2
    },
    {
      "key": "last_name",
      "title": "Last Name",
      "type": "text",
      "required": true,
      "minlength": 2
    },
    {
      "key": "email",
      "title": "Email",
      "type": "text",
      "unique": true,
      "regex": "/^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/",
      "regex_message": "You must enter a valid email."
    },
    {
      "key": "avatar",
      "title": "Avatar",
      "type": "file",
      "media_validation_type": "image"
    },
    {
      "key": "tagline",
      "title": "Tagline",
      "type": "text",
      "maxlength": 50
    }
  ]
}
```
## Fetching Metadata

When fetching Objects from the API, Metafields get converted into `key: value` pairs on the Object `metadata` property. See the [Objects model](/docs/api/objects) for more information.

`select` Metafields resolve to a **plain string** (the selected option value). `multi-select` Metafields resolve to a **string array** of selected values. For example, `category` and `tags` in the sample `metadata` below illustrate those shapes.

> Note: `select-dropdown` is deprecated. Use `select` for single-select or `multi-select` for multi-select in new content models. Existing `select-dropdown` fields continue to work and return `{ key, value }` objects in metadata.

```json
{
  "metadata": {
    "headline": "3030 Palo Alto Blvd.",
    "basic_text": "This home is a must see!",
    "extended_text": "<p>Some <strong>HTML content</strong> for <em>dramatic</em> effect!</p>",
    "markdown_text": "# Hello World!",
    "state": "California",
    "category": "Technology",
    "tags": ["Technology", "Business"],
    "author": {
      "title": "Author Name",
      "metadata": {
        "image": {
          "url": "https://cdn.cosmicjs.com/author-headshot.jpg",
          "imgix_url": "https://imgix.cosmicjs.com/author-headshot.jpg"
        }
      }
      // May include more nested data
    },
    "categories": [
      {
        "title": "Category 1"
        // May include more nested data
      },
      {
        "title": "Category 2"
        // May include more nested data
      },
    ],
  "hero": "https://cdn.cosmicjs.com/media-name-property-in-bucket.jpg",
  "gallery": [
    {
      "url": "https://cdn.cosmicjs.com/gallery-image-1.jpg",
      "imgix_url": "https://imgix.cosmicjs.com/gallery-image-1.jpg"
    },
    {
      "url": "https://cdn.cosmicjs.com/gallery-image-2.jpg",
      "imgix_url": "https://imgix.cosmicjs.com/gallery-image-2.jpg"
    },
    {
      "url": "https://cdn.cosmicjs.com/gallery-image-3.jpg",
      "imgix_url": "https://imgix.cosmicjs.com/gallery-image-3.jpg"
    },
  ],
  "listing_start_date": "2020-10-15",
  "json_data": {
    "strings": "cheese",
    "arrays": ["Bradbury", "Charles", "Ramono", "the last Jedi", "Liotta"],
    "objects": {
      "bools": true,
      "nestable": true
    }
  },
  "deposit_required": "The Other",
  "amenities": ["Pool", "Gym"],
  "this_is_great": true,
  "call_out_section": {
    "headline": "You're Going to Love it Here!",
    "section_content": "<p>You are going to <strong>love</strong> it in Cosmic Village. The best place to raise a team!</p>",
    "hero": {
      "url": "https://cdn.cosmicjs.com/big-beautiful-image.jpg",
      "imgix_url": "https://imgix.cosmicjs.com/big-beautiful-image.jpg"
    }
  },
  "testimonials": [
    {
      "name": "Fiona Apple",
      "quote": "This is the best place in the LA area!"
    },
    {
      "name": "Jon Brion",
      "quote": "I came for the great music, I stayed for the good vibes."
    }
  ]
}

```