> For the complete documentation index, see [llms.txt](https://docs.cortex.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cortex.io/ingesting-data-into-cortex/entities-overview/entities/custom-data.md).

# Adding custom data

Custom data extends Cortex's out-of-the-box metadata by letting you attach additional attributes to entities. It can be used in CQL queries and Scorecard rules.

Custom data can be defined manually in [the entity descriptor](#defining-custom-data-in-the-entity-descriptor), added programmatically [via API](#defining-custom-data-via-api), or sent through a [custom webhook integration](#defining-custom-data-via-webhook).

## Custom data vs. custom metrics

Cortex also offers [custom metrics for Eng Intelligence](/improve/eng-intelligence/custom-metrics.md). Note the following differences between custom data and custom metrics:

* **Custom data** - Used for static or slowly changing metadata (e.g. deployment environments, compliance statuses). Best for enriching entity details, reporting, and Scorecard rules. Note that new values overwrite previous ones for the same key, so it's not suited for time-sensitive tracking. Refer to the [use cases](#use-cases) below.
* **Custom metrics** - Used for time series or trending data (e.g. incident counts, SLOs). Designed for analytics; use them in dashboards, entity pages, and Scorecards. See [Custom metrics](/improve/eng-intelligence/custom-metrics.md) for more information.

## Defining custom data

There are a few ways to add custom data to an entity:

* **In the entity descriptor** - Best for low-volume, human-maintained data; requires updating the entity's YAML when the data changes.
* **Via REST API** (`POST`) - Best for data from automated processes like CI/CD pipelines.
* **Via webhook** - Useful when you don't have access to the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities.md#cortex-tag) or can't add authentication headers, as it requires neither.

### Defining custom data in the entity descriptor

{% hint style="info" %}
Learn more about [entity YAML descriptors](/ingesting-data-into-cortex/entities-overview/entities.md#defining-entities-via-yaml-file) in the Managing entities documentation.
{% endhint %}

The simplest way to add custom data is to define an object under `x-cortex-custom-metadata`:

```yaml
x-cortex-custom-metadata:
  team-owner: platform-engineering
  deployment-env: production
  compliance-status:
    value: SOC2
    description: Certified under SOC2 Type II as of 2024.
  pagerduty-enabled: true
```

<table><thead><tr><th width="79.8203125">Field</th><th width="424.35546875">Description</th><th align="center">Required</th></tr></thead><tbody><tr><td><code>key</code></td><td>Key or title for the custom data. Anything defined <strong>before</strong> the <code>:</code> serves as the <code>key</code>.</td><td align="center"><strong>✓</strong></td></tr><tr><td><code>value</code></td><td>Value for the custom data. Anything defined <strong>after</strong> the <code>:</code> is the <code>value</code>.</td><td align="center"><strong>✓</strong></td></tr></tbody></table>

Custom data supports any type: scalars (strings, numbers, booleans), objects, and lists. Once added, key-value pairs appear on the entity's custom data page, tagged as YAML.

#### **Adding descriptions**

To include a description alongside a value, use the explicit `value` + `description` syntax. Note that when a description is present, `value` must be explicitly defined (rather than inlined):

```yaml
x-cortex-custom-metadata:
  supported-regions:
    value: 3
    description: us-east-1, eu-west-1, ap-southeast-1
  on-call-rotations:
    value: 2
    description: Primary and secondary on-call rotations are active for this service.
```

<table><thead><tr><th width="128.27734375">Field</th><th width="379.828125">Description</th><th align="center">Required</th></tr></thead><tbody><tr><td><code>key</code></td><td>Key or title for the custom data. Anything defined <strong>before</strong> the <code>:</code> serves as the <code>key</code>.</td><td align="center"><strong>✓</strong></td></tr><tr><td><code>value</code></td><td>Value for the key; should be defined explicitly with <code>value:</code>.</td><td align="center"><strong>✓</strong></td></tr><tr><td><code>description</code></td><td>Description of the custom data</td><td align="center"><strong>✓</strong></td></tr></tbody></table>

{% hint style="info" %}
Descriptions are always optional, but if you want to add one, the `value` key is required.
{% endhint %}

### Defining custom data via API

You can pipe custom data directly into Cortex by POSTing to `/api/v1/catalog/{tag}/custom-data`, where `{tag}` is the entity's `x-cortex-tag`. The request body requires JSON. See the [Custom data API docs](/api/readme/custom-data.md) for authentication details and required fields.

**Key precedence and overwriting**

If a key is already defined in the entity descriptor, the API does not overwrite it. Instead, it returns the existing value with `YAML` as the source. To explicitly overwrite a YAML-defined value, use the `force=true` query parameter. That said, if you find yourself relying on `force=true`, it's worth updating or removing the field from the YAML to keep a clear source of truth.

{% hint style="info" %}
Custom data added via API displays with an API tag.
{% endhint %}

**Bulk upload**

To upload multiple keys for one or more entities at once, `PUT` to `/api/v1/catalog/custom-data`:

```json
{
  "values": {
    "payments-service": [
      {
        "key": "deployment-env",
        "value": "production",
        "description": "The environment this service is currently deployed to."
      }
    ],
    "user-auth-service": [
      {
        "key": "compliance-status",
        "value": {
          "certified": "SOC2",
          "last-audit": "2025-03-15",
          "reviewed-by": "security-team"
        }
      }
    ]
  }
}
```

Each tag can include multiple key-value objects, following the same shape as the single upload API.

### Defining custom data via webhook

Refer to [Custom webhook integrations](/ingesting-data-into-cortex/integrations/webhook.md)

## Data source hierarchy

When the same key is defined from multiple sources, Cortex resolves conflicts in the following order:

1. **Entity descriptor (YAML)** - The source of truth. Keys defined here cannot be overridden by the API or webhooks by default. Use `force=true` to override them via API, but note that the forced value will be overwritten the next time the entity descriptor is re-processed.
2. **API and webhooks** - Treated equally; either can override the other.

## Use cases

Custom data is flexible by design. Below are two of the most common ways teams put it to work.

### Cataloging

Cortex catalogs surface a lot out of the box—ownership, integration data, and more—but you may have internal fields that don't map to any integration. Custom data fills that gap. Common examples include:

* ***Which AWS zones is this deployed in?***
* ***What databases does this entity consume?***
* ***When was the last successful CI run?***

If the answers fit a fixed list, consider using [groups](/ingesting-data-into-cortex/entities-overview/entities/groups.md) instead. They display on an entity's details page and work well as catalog filters. Custom data is better suited for flexible or freeform values.

Once defined, custom data can be queried with the [Query builder](/standardize/cql.md#the-query-builder-tool), explored via [CQL reports](/standardize/cql/cql-reports.md), viewed directly on an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details.md), or added as a column in Data Explorer's [table view](/improve/eng-intelligence/data-explorer.md#configuring-table-view).

### Scorecards

Custom data integrates directly with Scorecards. When [adding a rule](/standardize/scorecards/create.md#step-3-create-a-rule), select **Custom data** from the **Integrations** drop-down menu. Cortex automatically surfaces variables based on the custom data you've defined.

<div align="left" data-with-frame="true"><figure><img src="/files/l8tiOvtSFPYiEOaFPIf6" alt="The &#x27;Custom data&#x27; option selected in the Integrations drop-down menu." width="563"><figcaption></figcaption></figure></div>

For more advanced use cases, push JSON payloads via the [custom data API](/api/readme/custom-data.md) and process them in a Scorecard using `jq`, or pass them as input to a custom OPA policy rule.
