# Cortex documentation

Code is no longer the bottleneck. Everything else is.

[Cortex](https://cortex.io/) is the EngOps Platform that keeps your entire engineering organization moving as one—fewer incidents, faster recovery, and developers spending time building instead of battling friction.

### Welcome to Cortex

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f4a1">💡</span> <strong>Solve Your Use Case</strong></td><td>Use Cortex to automate best practices and streamline actions for use cases like Production Readiness, AI Maturity, and Incident Management.</td><td></td><td><a href="/spaces/7F1UMLUuX7dkA693DijO">/spaces/7F1UMLUuX7dkA693DijO</a></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="26a1">⚡</span> <strong>Connect Data</strong></td><td>Pull in data from Git, Snyk, PagerDuty, and your other essential tools to build a complete picture of your software ecosystem.</td><td></td><td><a href="/pages/HKESDw5cb5tqBJcIAv3o">/pages/HKESDw5cb5tqBJcIAv3o</a></td></tr><tr><td>🔑 <strong>Define Ownership</strong></td><td>Establish clear ownership of services and entities to drive accountability, streamline incident response, and keep critical issues from falling through the cracks.</td><td></td><td><a href="/pages/3sA3UzKYpba4iDmzT7Gj">/pages/3sA3UzKYpba4iDmzT7Gj</a></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f5a5">🖥️</span> <strong>Configure GitOps</strong></td><td>Configure a GitOps workflow to manage entities in your Cortex workspace.</td><td></td><td><a href="/pages/KBttn6YUdEgixQGROHKf">/pages/KBttn6YUdEgixQGROHKf</a></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f517">🔗</span> <strong>Explore the API</strong></td><td>Build on top of Cortex using the API. Automate workflows, query your Catalog, and extend Scorecards.</td><td></td><td><a href="/spaces/nPgS8L9MAPtoOtdWdeDp">/spaces/nPgS8L9MAPtoOtdWdeDp</a></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f4c8">📈</span> <strong>Continuously Improve</strong></td><td>Measure baselines and identify bottlenecks. Take action and watch trends improve in real time.</td><td></td><td><a href="/pages/nZOyOBWYHpwwuH9q8HVF">/pages/nZOyOBWYHpwwuH9q8HVF</a></td></tr></tbody></table>

### Accelerate the path to engineering excellence

Engineering excellence is built on four pillars: **security**, **reliability**, **velocity**, and **efficiency**. But achieving all four requires more than good intentions. It requires clear ownership, complete visibility, and consistent standards across every team and service. Cortex gives you the foundation to get there.

Start with clear ownership and accountability so nothing falls through the cracks. Layer in complete visibility through the Catalog, drive a culture of continuous improvement with [Scorecards](/standardize/scorecards) and [Engineering Intelligence](/improve/eng-intelligence), and deliver a consistent developer experience through self-service [Workflows](/streamline/workflows).

***

#### SECURITY

Security best practices should be embedded in development from day one. Cortex lets you continuously check services for compliance and drive remediation with clear ownership and accountability.

* Monitor encryption, dependency health, and vulnerability status with customizable security compliance Scorecard templates.
* Automatically enforce security and compliance checks during service creation, ensuring every new service meets company-wide policies before it ships.
* Remediate vulnerabilities and compliance gaps by priority and deadline with [Initiatives](/improve/initiatives).
* Ensure consistent rollouts and CI/CD processes using Workflows.

<details>

<summary>How different personas drive security with Cortex</summary>

* **Engineering leaders** - Use [reports](/improve/reports) to understand current security posture and guide teams with actionable insights.
* **SREs** - Use Scorecards to maintain well-cataloged services, enabling faster and more confident incident response.
* **Security engineers** - Automate security checks, flag noncompliant services with Scorecards, and standardize remediation tasks with Workflows.

</details>

#### RELIABILITY

Reliability isn't just about uptime. It's about ensuring every service meets production-readiness standards before issues arise, and giving teams the context to respond quickly when they do.

* Automate readiness and operational maturity checks with customizable Scorecard templates that flag missing ownership, alerting, or logging configurations.
* Track DORA metrics and MTTR using Eng Intelligence dashboards.
* Enable fast incident response with Workflows to rollback, restart pods, and more.
* Give leaders and engineers a shared view of [Initiatives](/improve/initiatives), progress, and tasks on the [Engineering homepage](/streamline/homepage).

<details>

<summary>How different personas drive reliability with Cortex</summary>

* **Engineering leaders** - Use [reports](/improve/reports) to get a unified view of organization-wide service health and prioritize reliability Initiatives across teams.
* **Developers** - Use Scorecards to get clear visibility into whether services meet reliability standards.
* **SREs** - Automate production readiness checks via Scorecards to shift from reactive firefighting to proactive incident prevention.
* **Platform engineers** - Automate best practice enforcement via Scorecards and use Initiatives to keep reliability improvements moving by [syncing tasks directly with issue tracking tools](/improve/initiatives/issue-config).

</details>

#### VELOCITY

Slow, manual processes are one of the biggest blockers to shipping. Cortex removes the friction that keeps developers from moving fast without sacrificing standards.

* Provide automated golden paths that let developers bootstrap new services with security, observability, and operational standards pre-configured, so engineers aren't starting from scratch every time.
* Monitor cycle time, PR throughput, code coverage, and velocity trends with Eng Intelligence [velocity](/improve/eng-intelligence/dashboards/velocity-dashboard) and [DORA](/improve/eng-intelligence/dashboards/dora-dashboard) dashboards.
* Set clear standards and enforce best practices across teams and services with Scorecards.
* Automate common tasks like scaffolding new services or managing migrations with Workflows.
* Get quick answers about your workspace via [Cortex MCP](/get-started/mcp) for faster decision-making.

<details>

<summary>How different personas drive velocity with Cortex</summary>

* **Engineering leaders** - Leverage productivity metrics from Eng Intelligence during performance reviews and coaching conversations.
* **Platform engineers** - Eliminate back-and-forth by setting up a Workflow to handle access requests as a single approval flow that integrates into existing tooling.
* **Developers** - Use the [Engineering homepage](/streamline/homepage) to stay focused on priorities, not operational overhead.

</details>

#### EFFICIENCY

Engineering efficiency means more than moving fast. It means eliminating waste, reducing redundant work, and ensuring every team is aligned to the same standards.

* Gain real-time visibility into your software ecosystem to identify orphaned services, stale dependencies, and underutilized infrastructure before they become costly problems.
* Use Scorecards to measure and enforce standards for consistency, resource utilization, and migrations.
* Use [Initiatives](/improve/initiatives) to keep teams aligned and ensure migrations are completed on time.
* Automate repeatable tasks with Workflows to free engineers from operational overhead.

<details>

<summary>How different personas drive efficiency with Cortex</summary>

* **Engineering leaders** - Manage cloud costs and improve resource utilization by identifying services that are no longer actively maintained or are running outdated dependencies.
* **Platform engineers** - Use Scorecards to enforce standards during migrations, keeping projects on track without manual review cycles.
* **Developers** - Use the [Engineering homepage](/streamline/homepage) to gain insight into their tasks and priorities at a glance.

</details>

### Cortex video overview

See Cortex in action.

{% embed url="<https://www.youtube.com/watch?v=0ugYI8r1DwI>" %}


# Cortex quick start guide

This guide walks you through Cortex's core concepts and initial setup. By the end, you'll understand how Cortex works and how to start using it.

**Welcome to Cortex!**\
\
Cortex is an Engineering Operations Platform (EngOps) that brings your entire engineering ecosystem into a single, trusted source of truth. Instead of hunting through spreadsheets, wikis, and a dozen disconnected tools to answer basic questions like, *Who owns this service?*, *Is it production-ready?*, or *What depends on it?*, your team gets the answers at a glance, always up to date.

Under the hood, Cortex continuously polls your existing tools and stitches that data into a unified model of your software. On top of that model, you can define standards, automate self-service actions, and give every engineer the context they need to ship reliable software faster.

### The building blocks

Before you begin, take a minute to get familiar with the core Cortex concepts. They're the foundation for everything in this guide and everything that comes after.

#### Entities

An entity is anything in your engineering world that you want to track. Most commonly, that means services and the infrastructure they run on, but entities can also represent teams, domains, APIs, pipelines, ML models, or any other construct that matters to how you build software. Entities can own other entities, depend on each other, and roll up into higher-level groupings—which is what turns a flat list of components into a real map of your architecture.

#### Catalogs

A catalog is a curated view of your entities, defined by a filter you set: a specific entity type (like all services or all APIs), a group, or a custom CQL query. Rather than browsing everything at once, catalogs let you carve out focused slices of your ecosystem so the right people see the right things without the noise.

#### Scorecards

A scorecard is how you define and enforce quality standards across your entities. You set the rules (what "good" looks like), organize them into levels (bronze, silver, gold, or whatever progression fits), and Cortex continuously evaluates each entity against them. The result is a clear, always-current score for things like production readiness, security posture, or operational maturity.

#### Initiatives

An initiative is a focused, time-bound campaign for rolling out a specific improvement across your entities. You define the goal, e.g. *Migrate all services to Kubernetes by Q3*, scope it to the right entities, and set a deadline. Cortex tracks progress automatically, surfaces what's still outstanding, and keeps the right owners accountable.

#### Relationships / Dependencies

Relationships capture how your entities connect to one another, turning a flat list of components into a real map of your architecture. Some relationships are implicit and created automatically, like the hierarchy between domains, teams, and services, or the dependencies between services. Others are generic relationships that you configure to reflect the connections that matter to your organization, whether that's "calls", "stores data in", "deployed by", or anything else.

#### Entity descriptor (YAML)

Every entity in Cortex is backed by a YAML descriptor—a single file that captures its metadata, ownership, and context. Each `x-cortex-*` block defines a specific piece of information: owners, links to dashboards or runbooks, Slack channels, custom metadata, and more. You can edit descriptors directly in the Cortex UI, or manage them in your own repositories and sync them via GitOps—whichever fits your team's workflow.

#### Integrations

Integrations are the connections between Cortex and the tools your team already uses—GitHub, PagerDuty, Datadog, Jira, your cloud provider, and so on. Each integration pulls live data into Cortex and attaches it to the right entity automatically. A service in the catalog isn’t just a name; it’s a rich, current view of its on-call rotation, deployment history, open incidents, documentation, and dependencies.

#### The catalog

Your catalog is the collection of all your entities in one place. It’s searchable, filterable, and browsable. It's the home base your developers will return to every day to understand what exists, who owns it, and how healthy it is. As you add entities and turn on integrations, the catalog fills itself in and becomes the foundation for everything else Cortex can do: scorecards, self-service actions, and AI-powered insights.

#### Custom data

Custom data is how you extend Cortex with information specific to your organization. It includes user-defined metadata (any key-value context you want to track), audit trails that record how entities change over time, and operational health metrics like deploy frequency, lead time, and other indicators of how your software is actually performing. If the out-of-the-box integrations don't capture what your team needs, custom data fills the gap.


# Getting started: Logging in to Cortex and configuring your workspace

This article walks through logging in to Cortex for the first time. It also includes additional information for admins on how to configure the Cortex workspace.

### Logging in to Cortex

Follow the steps below to log in to Cortex.

1. Go to <https://app.getcortexapp.com/login>.
2. Enter your workspace name, then click **Sign in**.

When you first log in to your Cortex workspace, you are prompted through the steps of configuring your account and connecting data. See the video below for a demonstration:

{% embed url="<https://www.youtube.com/watch?v=yT6Ka0y_r80>" %}

### For Cortex Admins

Users with the `Admin` role have full access to everything in Cortex, from customizing the organization's workspace and setting up SSO to managing users and configuring entities. This section covers the essentials for getting your workspace set up and ready for your team.

{% hint style="info" %}
Access your Cortex workspace using the workspace ID provided to you by the Cortex team. If you are deploying Cortex on-premises, the Cortex team will provide you with access to an installer.
{% endhint %}

#### Setting up SSO

Your initial login is configured to use Google for Single Sign-On (SSO).

If you do not use a Google domain email address, contact the Cortex team at <help@cortex.io> to discuss initial access and [configuring an alternate SSO provider](/configure/settings/managing-users/configuring-sso).

#### Customizing the look of your workspace

A few quick tweaks to your workspace can help make it feel like part of your company's toolkit. Head to general settings to upload your logo, set a workspace name, and choose a brand color. See [Customizing your workspace](/configure/settings/workspace-customization) for more information.

#### Adding users to your workspace

With your account set up, you're ready to bring your team into Cortex. You can invite users one at a time or in bulk, and assign each person a role that reflects the level of access they need. See [Roles and permissions](/configure/settings/managing-users/permissioning) for more information.

Before you start inviting the broader team, it's strongly recommended to configure at least two users with the `Admin` role. Having a second admin ensures redundancy of access: if one admin is out of office, changes roles, or leaves the organization, you'll always have someone who can manage Cortex.

#### Additional resources

Go further with your initial setup! We recommend reviewing the following resources:

* [Onboarding management](/configure/settings/managing-users/onboarding-mgmt) - Stay informed about user onboarding statuses.
* [IP allowlist](/configure/settings/ip-allowlist) - Use the IP allowlist to restrict which networks can access your Cortex workspace.
* [Workspace settings](/configure/settings) - Further customize your Cortex workspace and view audit logs.


# Laying the foundation: Data modeling, integrations, and identity mapping

Before you can get the most out of Cortex, a few foundational pieces need to be in place. This article walks through planning your data model, configuring your first integrations, and mapping user identities across tools—the groundwork that makes everything else in Cortex work smoothly.

### Data modeling

Your data model is the foundation of everything else in Cortex, so it's worth planning before you start importing entities. Think about which parts of your engineering ecosystem you want to represent, how they relate to one another, and how different teams will want to slice and view them.

* Identify the key entities you want to represent in your catalogs. See [Managing entities](/ingesting-data-into-cortex/entities-overview/entities) for a rundown of the default entity types.
* Create [custom entity types](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/entity-types) if the defaults don't fit your use case.
* [Set up catalogs](/ingesting-data-into-cortex/catalogs) to organize the entities that make up your infrastructure.

### Integrating your tools with Cortex

As you integrate your tools with Cortex, it's also possible to streamline work during an incident, efficiently track issues, monitor your code for vulnerabilities, and more. See the [full list of available integrations](/ingesting-data-into-cortex/integrations).

Cortex meets your team where they already work, with integrations across version control, project management, on-call, communication, infrastructure, security, issue tracking, code quality, and beyond.

### Configuring identity mappings and reviewing mapped services

[Identity mappings](/configure/settings/managing-users/identity-mapping) connect accounts from your integrations to the right Cortex users by matching on name or email. This keeps integrations working correctly for each team member and ensures features like the Developer Homepage and Eng Intelligence show the right data for the right people.

Cortex handles most matches automatically, but when account details differ across tools, admins can review and map users manually under **Settings > Identity mappings**.

#### Reviewing mapped services

Cortex recommends connections for your services. For example, if you connected PagerDuty, Slack, and Jira, then Cortex will recommend an entity's on-call service, Slack channel, and Jira project. You can change these details before confirmation.


# Building on the foundation: Catalogs, Scorecards, Workflows, and Eng Intelligence

With your foundation in place, it's time to put Cortex to work. This article covers the core features your team will use every day and how they turn your connected data into real visibility, accountability, and action.

### Working with the catalog

A [catalog](/ingesting-data-into-cortex/catalogs) is a defined selection of entities you use to track the components of your infrastructure—services, domains, cloud resources, and more. Entities are defined in YAML, but catalogs are created in the Cortex UI and act like filters that group related entities together. A single entity can belong to multiple catalogs.\
\
Cortex includes four built-in catalogs: Services, Infrastructure (with AWS, Azure, and Google Cloud resources pulled in automatically), Domains (displayed hierarchically), and Teams (displayed hierarchically with a Scorecard leaderboard).\
\
You can rename the defaults or create custom catalogs to match your organization's structure.

### Understanding Scorecards

[Scorecards](/standardize/scorecards) are how you establish and enforce standards across your entities—whether that's defining best practices, tracking migrations, promoting accountability, standardizing configuration, or setting maturity benchmarks. Each Scorecard evaluates entities against a set of rules, which can reference metadata within Cortex or pull data from third-party integrations. Levels and points add a layer of gamification, giving developers clear, incremental goals.\
\
Scorecards are designed for ongoing standards, not time-bound pushes. When you need to hit a specific deadline, create an [Initiative](/improve/initiatives) to drive focused progress by a target date.

#### Reports

Use reporting in Cortex to track how entities perform against Scorecards, analyze Scorecard trends over time, and surface the areas that need attention. Reports apply to published Scorecards in your workspace. See [Reports](/improve/reports) for more information.\
\
Cortex offers several built-in reports out of the box: Executive, All Scorecards, Bird's Eye, Progress, and Report Card.

### Using Workflows

Engineering teams use [Workflows](/streamline/workflows) when they need to standardize and automate high-stakes operations like service creation, access provisioning, or incident response, especially when those processes involve multiple tools, people, or approval steps. They're also useful for onboarding, where repeatability and speed matter.

### Leveraging Eng Intelligence

[Eng Intelligence](/improve/eng-intelligence) gives engineering leaders a clear, data-driven view of how their organization builds and ships software. Surface bottlenecks in the pull request lifecycle, measure incident response, understand cross-team activity, and identify where to dig deeper.\
\
Eng Intelligence in Cortex includes:

* Dashboards
  * [DORA Dashboard](/improve/eng-intelligence/dashboards/dora-dashboard) - the speed, reliability, and efficiency of your development practices at a glance.
  * [Velocity Dashboard](/improve/eng-intelligence/dashboards/velocity-dashboard) - team progress across the software development lifecycle.
  * [Copilot Dashboard](/improve/eng-intelligence/dashboards/ai-impact) - Copilot adoption and engagement across engineering.
  * [Custom Dashboards](/improve/eng-intelligence/dashboards/custom) - shared views tailored to the metrics your organization cares about most.
* [Metrics Explorer](/improve/eng-intelligence/metrics-explorer) - Explore trends over time and drill into the underlying data, covering deploys, version control, project management (Jira), and incident management (PagerDuty).
* [Custom metrics](/improve/eng-intelligence/custom-metrics) - Define your own time series metrics to power Eng Intelligence analytics, drawing from your Cortex integrations or internal data sources.

<br>


# Going further with Cortex

With the foundation laid and the core features in place, you're ready to take Cortex further. This article covers the capabilities that help you tailor Cortex to your organization.

### Tracking ownership with teams

In Cortex, teams play two roles: they're entities that represent your organization, and they're the owners of entities in your catalogs. Ownership is central to how Cortex works as organizations rely on it to establish clear accountability for services, data, and everything else in the catalog. It also determines who receives notifications from Cortex, including on-call changes, Scorecard updates, and other alerts.\
\
Like other [entities](/ingesting-data-into-cortex/entities-overview/entities), teams can be evaluated with [Scorecards](/standardize/scorecards), enriched by [integrations](/ingesting-data-into-cortex/integrations), and extended with [custom data](/ingesting-data-into-cortex/entities-overview/entities/custom-data). They can be organized into hierarchies, and their activity can be tracked and analyzed in [Eng Intelligence](/improve/eng-intelligence). You can create teams manually in Cortex or pull them in automatically from your integrations.

### Building your own plugin

When Cortex doesn't have exactly what you need out of the box, [plugins](/streamline/plugins) let you build it yourself. Use them to support custom workflows, surface data from internal systems, or connect tools Cortex doesn't natively integrate with.\
\
Each plugin is a single HTML file rendered inside an iframe within Cortex. Plugin proxies handle CORS restrictions and can add custom headers and secrets to outbound requests, making it easy to work with external APIs. Plugins also get contextual information about where they're running in the app, so they can adapt what they show.

### Managing external docs

Documentation is often one of the biggest pain points in a growing engineering org—scattered across wikis, Google Docs, repos, and shared drives, with no easy way to tell what's current or relevant. Cortex solves this by becoming the source of truth for your external docs. You can aggregate documentation onto the entities it relates to, so a service's runbook, architecture notes, and onboarding guide all live right next to its ownership and health information. See [Adding external documentation](/ingesting-data-into-cortex/entities-overview/entities/external-docs) for more information.

### Using GitOps with Cortex

Instead of managing everything through the Cortex UI, you can take a [GitOps approach](/configure/gitops).\
\
GitOps is a practice that treats configuration the same way engineering teams already treat code: stored in a Git repository, reviewed through pull requests, and deployed automatically when changes are merged. Applied to Cortex, that means your entities, Scorecards, and Workflows are defined as descriptor files in a repo you own. When someone opens a PR to update a descriptor, your team reviews it like any other change; once it's merged, Cortex picks it up and syncs the update automatically.\
\
This approach offers several advantages:

* **Version-controlled metadata** - Every change has history, context, and an author.
* **A single source of truth** - The repository where your code lives also holds the definitions of how that code is represented in Cortex.
* **Full ownership of your data** - Descriptors live in your repository, not locked inside the UI.
* **Clear auditability** - GitOps logs let you monitor and track every sync, making it easy to debug issues or review changes.


# Additional Cortex resources

We’re excited for you to achieve engineering excellence with Cortex!

Beyond our extensive help center, we offer a range of other ways to help you get the most out of Cortex.

### Cortex Academy

Cortex Academy helps you get more out of Cortex, faster. Through courses organized by product area and use case, you'll build practical expertise on the features and workflows most relevant to your role. A mix of short videos, interactive exercises, reflections, and quizzes keeps the material engaging and easy to apply to your day-to-day work.

[Go to the Academy](https://academy.cortex.io/)

{% hint style="success" %}
Looking for a quick introduction to Cortex? Check out the [Cortex 101 video](https://academy.cortex.io/learn/video/cortex-101).
{% endhint %}

### AI Docs Assistant

At the top of the docs, click **Ask**, or use the keyboard shortcut `CMD+K` to open the AI Docs Assistant, powered by Kapa. Ask questions in natural language and receive quick instructions.

The AI search pulls from several resources, so you can get help with everything from setup instructions to troubleshooting steps.

<div align="left" data-with-frame="true"><figure><img src="/files/6L39nb8fqaZ1MWeQ76qe" alt="The AI Docs Assistant in the Cortex help center." width="563"><figcaption></figcaption></figure></div>

The Docs Assistant is also available in your Cortex workspace. Use the keyboard shortcut `CMD+K` in Cortex, then click the **Ask AI icon**. Enter a question and get answers without having to leave Cortex.

<div align="left" data-with-frame="true"><figure><img src="/files/0dEhYUPXZwxiaO2NQu7H" alt="The AI Docs Assistant in the Cortex app." width="563"><figcaption></figcaption></figure></div>

### Cortex blog

Visit the [Cortex blog](https://www.cortex.io/blog) to stay current with engineering insights, product updates, and best practices.

### Cortex webinars and events

Visit the Cortex [resources and events page](https://www.cortex.io/resources) to keep up to date with Cortex-related events and webinars!

### Cortex beta feature support

Participating in a beta? Learn more about the [Cortex beta program, support for beta features, and release phases](/resources/beta).

### Cortex Professional Services

To ensure a smooth implementation, partner with Cortex Professional Services (PS) for expert guidance and hands-on assistance with data modeling, entity ownership, and more.

Contact the Professional Services team at <help@cortex.io> to learn how we can support your implementation and adoption journey.


# Cortex AI Assistant

We're excited to announce a public beta for the Cortex AI Assistant, available through Slack. It puts all the data in Cortex at your fingertips, without having to leave where you work or having to find the data yourself in the UI. Ask natural language questions about your services, teams, Scorecards, Initiatives, and more without leaving Slack.

It can answer simple questions like, ***What services does my team own?*** or ***Who's on-call for payments-api?*** or ***What's the production readiness score for*** **`checkout-service`*****?***, but it can also do so much more.

Here are a few prompt examples for you to get started with:

* ***What are the patterns of incidents on my team over the last 2 quarters? What areas do you recommend we invest in to improve the reliability of our services?***
* ***Give me a summary of everything I worked on and my key accomplishments over the last quarter.***
* ***Has there been an increase in PR sizes recently? Does that correlate with longer review times?***
* ***What is our deployment frequency for the last 30 days across the services I own? Are there any patterns that may be causing that to change compared to the last quarter?***

See the [Cortex AI prompt library](/get-started/library) for a full list of prompt patterns organized by use case and role.

## How it works

{% hint style="info" %}
The Cortex AI Assistant requires the latest version of the Cortex Slack app. If you installed the app before February 2025, you'll need to update it before you can use the AI Assistant. Slack administrator permissions are required to perform the update.

To install, go to [Slack settings](https://app.getcortexapp.com/admin/integrations/slack) in Cortex. Delete the existing configuration and reinstall following the prompts.
{% endhint %}

When you mention `@Cortex` in a Slack channel or direct message, the AI Assistant:

1. Interprets your natural language query
2. Determines which Cortex API endpoints to call
3. Retrieves the relevant data from your Cortex workspace
4. Returns a formatted response in Slack

{% hint style="info" %}
The AI Assistant is currently read-only, so it can query information from Cortex but cannot make changes or write data.
{% endhint %}

### Threading and conversation context

The Cortex AI Assistant supports threaded conversations, allowing you to ask follow-up questions that build on prior context within the same thread. How it works:

* **Start a conversation** - Mention `@Cortex` in any private channel or directly to the `@cortex` app in the with your initial question. The bot responds in a thread.
* **Ask follow-ups in the thread** - Reply in the same thread with additional questions. The AI assistant retains context from the conversation, so you can drill down without repeating information.
* **Each thread is a separate conversation** - Context is scoped to the thread. Starting a new top-level message begins a fresh conversation with no prior context.

### Available capabilities

The Cortex AI Assistant can access the following Cortex API endpoints:

<table data-full-width="false"><thead><tr><th width="283.66015625">Capability</th><th>Description</th></tr></thead><tbody><tr><td><strong>Entity details</strong></td><td>Look up ownership, metadata, and custom data for any entity</td></tr><tr><td><strong>Entity descriptors</strong></td><td>View and list entity descriptors (YAML definitions)</td></tr><tr><td><strong>Dependencies</strong></td><td>List incoming and outgoing dependencies for an entity</td></tr><tr><td><strong>On-call</strong></td><td>Check who is currently on-call for an entity</td></tr><tr><td><strong>Scorecards</strong></td><td>List Scorecards, view scores, and get next-step recommendations</td></tr><tr><td><strong>Initiatives</strong></td><td>List and inspect Initiatives and their progress</td></tr><tr><td><strong>Relationships</strong></td><td>Explore entity relationships and relationship types</td></tr><tr><td><strong>Team details</strong></td><td>View team membership, sourcing, and contact channels</td></tr><tr><td><strong>Workspace context</strong></td><td>Query "my" entities and how they perform against Scorecards</td></tr><tr><td><strong>Eng Intelligence metrics / traces</strong></td><td>Query DORA metrics, incident trends, PR data, and other engineering performance indicators</td></tr><tr><td><strong>Deployments</strong></td><td>Search deployments across the workspace by environment, type, entity, and time range; list available deployment environments</td></tr></tbody></table>

### Providing feedback

After each response, the AI assistant displays reaction emoji options. You can react with `:thumbs_up:` (👍) or `:thumbs_down:` (👎) to provide feedback on the quality of the answer. This feedback helps improve the responses over time.

## Crafting effective prompts

Getting useful output from any AI assistant comes down to how you ask. Be sure to write prompts that are clear, specific, and designed to get you the response you need.

* **Be specific** - Instead of ***Tell me about services***, you could say, ***Show me all critical services failing the Production Readiness Scorecard***. This provides you with more actionable information.
* **Combine multiple questions when context helps** - Cortex handles complex prompts like ***Who owns orders-api, when was it last deployed, and are there any open incidents?*** You receive richer context in response to one question instead of piecing together three separate queries.
* **Reference your organization's specific constructs** - If you've defined custom Scorecards or Initiatives in Cortex, reference them by name. Cortex understands your organization's specific standards and can query against them directly.
* **Use follow-up questions to drill down** - Start broad, then go narrow. ***Show me services with failing Scorecards***, followed by ***What specific checks is checkout-service failing?*** moves you from landscape view to action items.
* **Build a library of your most-used prompts** - If you ask the same question every Monday morning, save it. Some teams maintain shared prompt libraries so everyone can benefit from patterns that work.

See the [Cortex AI prompt library](/get-started/library) for a full list of prompt patterns organized by use case and role.

## Configuring the Cortex AI Assistant

For instructions on configuring the AI Assistant, refer to [Configuring the integration for Slack](/ingesting-data-into-cortex/integrations/slack).

## Troubleshooting and FAQ

See [Slack integration FAQ and troubleshooting](/ingesting-data-into-cortex/integrations/slack/slack-integration-faq-and-troubleshooting).


# Cortex AI prompt library

This article contains prompts for both the [Cortex MCP](/get-started/mcp) and the [AI Assistant](/get-started/cortex-ai-assistant), inspired by how high-performing engineering teams use Cortex every day. The prompt examples in this article represent effective patterns across different roles and workflows. Use them as a starting point for building your own prompt library tailored to your team and organization.

Remember:

* **Be specific** - Instead of ***Tell me about services.***, you could say, ***Show me all critical services failing the Production Readiness Scorecard***. This provides you with more actionable information.
* **Combine multiple questions when context helps** - Cortex handles complex prompts like ***Who owns orders-api, when was it last deployed, and are there any open incidents?*** You receive richer context in response to one question instead of piecing together three separate queries.
* **Reference your organization's specific constructs** - If you've defined custom Scorecards or Initiatives in Cortex, reference them by name. Cortex understands your organization's specific standards and can query against them directly.
* **Use follow-up questions to drill down** - Start broad, then go narrow. ***Show me services with failing Scorecards***, followed by ***What specific checks is checkout-service failing?*** moves you from landscape view to action items.
* **Build a library of your most-used prompts** - If you ask the same question every Monday morning, save it. Some teams maintain shared prompt libraries so everyone can benefit from patterns that work.

## Use-case based prompts

### Incident response

| Prompt                                                                      | What it does                                                                                                             |
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| ***Who owns payments-api and who's currently on-call?***                    | Gets you the right contact immediately so you can escalate or start investigating.                                       |
| ***What changed in checkout-service in the last 24 hours?***                | Most incidents trace back to a recent change, so this is usually the fastest path to identifying the root cause.         |
| ***Which services depend on user-auth? Who do I need to loop in?***         | Understanding the blast radius of an incident helps you get the right teams involved before downstream impact compounds. |
| ***What are the top P1 incident drivers on my team this quarter?***         | Surfaces patterns across incidents so you can address systemic causes rather than treating each one as isolated.         |
| ***How is our mean time to resolution trending compared to last quarter?*** | Gives you a clear signal on whether your reliability investments are actually improving response time.                   |

### Service ownership

| Prompt                                                                                     | What it does                                                                                                         |
| ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| ***Which services have no defined owner?***                                                | Unowned services are the ones most likely to fall through the cracks during an incident, audit, or migration.        |
| ***Show me all Tier 1 services with no team assigned.***                                   | Tier 1 services without ownership represent your highest-risk gap.                                                   |
| ***Which of our upstream dependencies have no on-call rotation configured?***              | A dependency without on-call coverage means there's no clear path to resolution if it goes down after working hours. |
| ***If the data-platform team goes on a code freeze, which of our services are affected?*** | Helps you proactively identify risk and communicate impact before a freeze causes surprises.                         |

### Production readiness

| Prompt                                                                            | What it does                                                                                                 |
| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| ***Which of my team's services are failing the Production Readiness scorecard?*** | Gives you a prioritized view of which services need attention before gaps become incidents.                  |
| ***Which services are Tier 1 but haven't passed Production Readiness?***          | Your most critical services should meet the highest bar; this tells you exactly where that's not the case.   |
| ***What are the most common gaps across my team's services?***                    | Identifying patterns in failures helps you address systemic issues rather than fixing services one by one.   |
| ***Which services have no runbook, no on-call rotation, or no defined owner?***   | These three gaps together represent a service that no one can reliably respond to when something goes wrong. |

### Engineering health and trends

| Prompt                                                                                               | What it does                                                                                                                               |
| ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| ***What are the incident patterns on my team over the last two quarters?***                          | Reveals whether your reliability posture is improving over time or if the same failure modes keep recurring.                               |
| ***Has PR size increased recently? Does that correlate with longer review times?***                  | Large PRs slow down review cycles and introduce more risk. This tells you whether the two are connected on your team.                      |
| ***Which teams have improved their deploy frequency the most this quarter?***                        | Deployment frequency is a leading indicator of team velocity and confidence, so knowing who's improving helps you identify what's working. |
| ***What's the overall operational maturity trend for my org over the last 6 months?***               | A high-level view of whether your implementation investments are moving the needle across the organization.                                |
| ***Summarize the key engineering health metrics for my org — I need this for a leadership review.*** | Pulls together the data you'd otherwise spend hours assembling from dashboards, spreadsheets, and status updates.                          |

### New hire onboarding

| Prompt                                                                             | What it does                                                                                                          |
| ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| ***What dependencies does my team's services have and who owns them?***            | The fastest way to understand your team's scope of responsibility without waiting for someone to walk you through it. |
| ***Which of our services have open action items or are failing their Scorecard?*** | Surfaces the most pressing work on your team so you can start contributing without needing a full handoff.            |
| ***Give me a summary of what my team has shipped in the last 90 days.***           | Gets you up to speed on recent deployments so you can have informed conversations with your team from day one.        |

### Migration tracking

| Prompt                                                                                  | What it does                                                                                                                 |
| --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| ***Which services have been migrated to \[NEW PLATFORM] and which are still pending?*** | Gives you a real-time view of migration progress without chasing teams for status updates.                                   |
| ***Which teams haven't completed the migration yet and what's blocking them?***         | Surfaces where the migration is stalling so you can direct support to the right places before deadlines slip.                |
| ***Which migrated services are failing their scorecard since the cutover?***            | Catches regressions introduced by the migration before they turn into incidents or compliance gaps.                          |
| ***What's the migration completion rate across the org this quarter?***                 | Tracks overall migration progress across the org so you know whether you're on pace to hit your target or need to intervene. |

## Role-based prompts

### Prompts for engineers

The best prompts for engineers eliminate context switching at the moments when focus matters most.

#### Understanding unfamiliar services

| Prompt                                                                                                                   | What it does                                                                                                                                                                                                                                                                                                                                                       |
| ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| ***Tell me about the \[SERVICE NAME] service, including who owns it, what it does, and where the documentation lives.*** | Pulls everything from your [Cortex catalog](https://www.cortex.io/products/service-catalog) at once. You get ownership, a description of what the service does, links to documentation, and the team's communication channels. Instead of hunting across wikis, Slack, and GitHub, you have the context you need to start working.                                 |
| ***Show me the dependencies for \[SERVICE NAME]. Which services does it depend on, and which services depend on it?***   | Understanding the dependency graph is critical when planning changes with potential downstream impact. This prompt reveals what might break and which teams need to be in the conversation before you make a move.                                                                                                                                                 |
| ***Which Scorecard is \[SERVICE NAME] failing, and what do I need to fix?***                                             | Transforms maintenance from reactive to proactive. Instead of waiting for your platform team to flag issues or discovering gaps during an incident, you see exactly which Scorecards are failing and what specific checks need attention. You can address production readiness, security, or documentation gaps on your own schedule, before they become blockers. |

#### During code review

| Prompt                                                                                                     | What it does                                                                                                                                                                                         |
| ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ***Check the Scorecards for \[SERVICE NAME]. Does this service meet our production readiness standards?*** | Starting here when you're unfamiliar with a service changes the conversation. If the service is already failing key Scorecards, you'll know which questions to ask and where the risks actually are. |
| ***Show me recent incidents for \[SERVICE NAME].***                                                        | Past incidents tell you where a service has been fragile. When you see that history before approving changes, you can evaluate whether the PR addresses root causes or introduces new failure modes. |

#### Tracking work

| Prompt                                                                                      | What it does                                                                                                                                                                                                                                                                                                                                                                  |
| ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ***What Initiatives are assigned to the Engineering team, and what's the status of each?*** | Condenses your weekly status check into a single query. Run it at the start of your week or during standup and you get a complete picture of your Initiative commitments and their current state. Instead of navigating to the Cortex web UI or mentally tracking what you're responsible for, you see everything assigned to you without leaving your IDE or chat interface. |
| ***Show me the details for \[INITIATIVE NAME]. What still needs to be done?***              | When you're ready to make progress on a specific Initiative, this surfaces the remaining tasks and their current state. You know exactly what's left and where to focus.                                                                                                                                                                                                      |

### Prompts for engineering leaders

The best prompts for engineering leaders are about trends, patterns, and the health of systems; these prompts surface the signals that inform strategic decisions.

#### Understanding team health

| Prompt                                                                                     | What it does                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ***Show me MTTR trends over the last quarter. How has it changed?***                       | Incident response either gets faster or it doesn't. If MTTR is climbing, something in your system has degraded. This prompt gives you the trend line and a clear signal to investigate process or tooling gaps.                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ***Which teams have the most failing Scorecards right now?***                              | Surfaces which teams are struggling with compliance or buried in technical debt. The answer reveals where support and resources should flow. Instead of waiting for teams to escalate problems or discovering issues through incident patterns, you have a clear view of which teams need help right now. That visibility lets you have proactive conversations about priorities, staffing, or process changes before compliance gaps become production incidents.                                                                                                                                                                       |
| ***How has deployment frequency changed over the last six months for the Platform team?*** | <p>Deployment frequency serves as a proxy for both velocity and confidence. When you track this metric over time, you get clear evidence of whether your investments in tooling and process improvements are actually working.</p><p>If deployment frequency is climbing, teams are shipping faster and feel confident doing it. If it's flat or declining despite investments, you need to investigate whether new tools are adding friction, whether processes are getting in the way, or whether something else is slowing teams down. The trend line tells you whether to double down on your current approach or change course.</p> |

#### Tracking AI adoption impact

| Prompt                                                                                              | What it does                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ***How has AI adoption impacted MTTR and deployment frequency over the last quarter?***             | <p>Connects AI spending directly to concrete business outcomes. When you run this query, you're comparing metrics before and after AI tool adoption. If MTTR dropped and deployment frequency increased after rolling out Copilot or similar tools, you have hard data to justify continued investment and potentially expand the rollout.</p><p>If the metrics haven't moved despite adoption, you need to ask different questions: Are teams actually using the tools? Do they need more training? Are the tools solving the wrong problems? The comparison gives you evidence to either double down on your AI strategy or course-correct before spending more.</p>                                                              |
| ***Which teams have adopted AI tools, and how does their velocity compare to teams that haven't?*** | <p>Reveals whether AI adoption is actually delivering the productivity gains you expected. The comparison between adopters and non-adopters gives you a clear control group to measure impact. If teams using AI tools show meaningfully higher velocity, you have validation to expand the rollout and invest more.</p><p>If there's no significant difference, or if adopters are actually slower, you need to understand why. Maybe teams need better training on how to use the tools effectively. Maybe the tools work better for certain types of work than others. Maybe adoption is superficial and teams aren't integrating the tools into their actual workflows. The data points you toward the right interventions.</p> |

#### Spotting bottlenecks

| Prompt                                                                    | What it does                                                                                                                                                                                                     |
| ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ***Where are the biggest bottlenecks slowing down the Checkout team?***   | When a team's velocity drops unexpectedly, this surfaces the patterns that sprint metrics miss: services with high incident rates, missing documentation, or blocked Initiatives. You get data, not speculation. |
| ***Show me services with the highest incident rates in the last month.*** | High incident rates point to deeper reliability issues. This tells you where to invest in stability before those services become everyone's problem.                                                             |

### Prompts for platform teams

The best prompts for platform teams show you where adoption is working, where it's stalled, and which teams need support.

#### Tracking standards adoption

| Prompt                                                                                                    | What it does                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ***Show me how teams are performing on the Production Readiness Scorecard. Which services are failing?*** | Gives you a complete view of compliance across the organization without manually checking each team's services. You see which teams are struggling to meet standards and which services create the most risk. The answer tells you where to focus your enablement efforts and which conversations to prioritize. Instead of discovering compliance gaps reactively during incidents or audits, you have a real-time picture of organizational health.                                                                                                                                                                                                         |
| ***Which services don't have runbooks, and who owns them?***                                              | <p>Missing runbooks are incidents waiting to happen. When something breaks at 3 AM, responders need clear guidance to restore service quickly. This prompt shows you exactly which services lack that critical documentation and who's responsible for creating it.</p><p>With this information, you can prioritize outreach based on service criticality. A critical payment service without a runbook demands immediate attention, while a lower-tier internal tool might wait. Instead of discovering documentation gaps during an active incident when every minute counts, you can systematically close them before they cost you hours of downtime.</p> |
| ***Show me AI maturity Scorecard results across all teams. Where are the biggest gaps?***                 | If you're driving AI adoption, this reveals which aspects of maturity need attention. The gaps tell you whether teams need training, tooling, process changes, or something else entirely.                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |

#### Managing Initiatives

| Prompt                                                                                                                 | What it does                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ***Which services are blocking completion of the \[INITIATIVE NAME]?***                                                | When an initiative stalls, this identifies exactly which services or teams are holding things up. Now you know where to focus your attention and who needs support.                                                                                                                                                                                                                                                             |
| ***Show me progress on the Kubernetes Migration Initiative. Which teams are on track, and which are falling behind?*** | Surfaces real-time status across every team involved in the initiative without sending Slack messages or requesting manual updates. You get an immediate picture of which teams are making progress, which are stuck, and which haven't started. That visibility lets you direct support and resources to the teams that need it most, rather than treating every team the same or discovering delays only when deadlines slip. |
| ***Give me a plan to get the Checkout team back on track with production readiness.***                                 | Once you've identified a team falling behind, this generates a concrete action plan based on the specific gaps in their Scorecards and service metadata. You move straight to solutions.                                                                                                                                                                                                                                        |

#### Gap analysis

| Prompt                                                            | What it does                                                                                                                                                                                                  |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ***Which critical services are missing SLOs?***                   | SLOs are foundational to reliability. This scopes the gap and identifies which services should be prioritized based on business impact before an incident forces the conversation.                            |
| ***Show me services without proper monitoring. What's missing?*** | Monitoring gaps are blind spots waiting to bite you during incidents. This surfaces which services need instrumentation and what specific monitoring is absent, so you can build a targeted remediation plan. |

### Prompts for SREs

The best prompts for SRE teams focus on proactive incident prevention or responding quickly to a incident in progress.

#### During incidents

| Prompt                                                                                          | What it does                                                                                                                                                                                                             |
| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| ***Who's on call for \[SERVICE NAME] right now, and when was it last deployed?***               | The first question in almost every incident. One prompt gets you the owner, the on-call contact, and recent deployment history. You can escalate or start investigating without hunting through five different systems.  |
| ***Show me recent deploys and changes for \[SERVICE NAME].***                                   | Most incidents trace back to recent changes. This gives you a timeline pointing to likely culprits so you can focus your investigation on what actually changed.                                                         |
| ***Show me the incident readiness Scorecard for \[SERVICE NAME]. Are we prepared to respond?*** | Not all services are equally ready for incidents. This tells you whether runbooks exist, whether monitoring is in place, and whether escalation paths are documented. You know what tools you have before you need them. |

#### Proactive reliability work

| Prompt                                                                     | What it does                                                                                                                                                                                     |
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| ***Show me services with the highest MTTR in the last month.***            | High MTTR means certain services are consistently difficult to debug or restore. This tells you where reliability improvements will have the biggest impact on your time and your team's sanity. |
| ***Which critical services have had the most incidents recently?***        | Frequent incidents signal deeper problems that incident response won't fix. This helps you spot patterns and prioritize services that need architectural investigation, not just patches.        |
| ***Show me services that are missing runbooks or escalation procedures.*** | When incidents happen, responders need clear guidance. This identifies documentation gaps that will slow response time before they cost you hours during an outage.                              |

### Prompts for security engineering teams

The best prompts for security engineers help them monitor, audit, and enforce security posture across services.

#### Compliance monitoring

| Prompt                                                | What it does                                                                                                                                                                                                                                                                                                                              |
| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ***Which services are failing our SOC-2 Scorecard?*** | Gives you a view of SOC-2 compliance across the organization without manually checking each team's services. The answer tells you where to focus your efforts and which conversations to prioritize. Instead of discovering compliance gaps reactively during incidents or audits, you have a real-time picture of organizational health. |

#### Proactive security health

| Prompt                                                                             | What it does                                                                                                                                                                                                                                                                 |
| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ***Which services have no on-call rotation configured in PagerDuty?***             | When incidents happen, it's important to have on-call information readily available to ensure a fast response time.                                                                                                                                                          |
| ***What is the progress on my Security Initiative and what are some quick wins?*** | Surfaces real-time status for an Initiative without requesting manual updates from team members. You get an immediate picture of which entities are making progress and which are not. That visibility lets you direct support and resources to the teams that need it most. |
| ***List all services with open vulnerabilities labeled CRITICAL or HIGH.***        | Helps determine which services need attention.                                                                                                                                                                                                                               |

### Prompts for product managers

The best prompts for product managers focus on visibility, delivery health, and compliance to engineering standards that affect product velocity and quality.

#### Delivery and health metrics

| Prompt                                                                             | What it does                                                                                  |
| ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| ***Which services in the \[PRODUCT AREA] domain are failing their DORA metrics?*** | Gives quick insight into which services in that product area domain are failing DORA metrics. |

#### Initiatives and adoption tracking

| Prompt                                                                               | What it does                                                                               |
| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
| ***Give me all currently active initiatives and ideas for how I can improve them.*** | Helps track progress on key initiatives and ensure teams are moving toward business goals. |
| ***Give me links to the docs and runbooks for \[REPOSITORY].***                      | Helps find the documentation for a feature's related repository.                           |


# Cortex MCP

The [Cortex MCP](https://github.com/cortexapps/cortex-mcp) is a Model Context Protocol server that brings your engineering data into the tools your team already works in, enabling natural language queries across your catalog, Scorecards, metrics, and Initiatives.

It provides:

* **Natural language querying** - Ask questions in plain English rather than constructing API calls directly
* **Contextual awareness** - Maintains awareness of your workspace's structure when answering questions, so responses are grounded in your org's actual data
* **AI-assisted insights** - Synthesizes Eng Intelligence metrics, Scorecard status, ownership, and initiative data into actionable recommendations
* **Cross-tool availability** - Surfaces inside the tools your team already uses, making it an in-workflow intelligence layer rather than a standalone API
* **Prompt-driven workflows** - Supports complex, multi-part queries that combine data from multiple Cortex systems in a single response
* **Documentation querying** - The remote MCP implementation includes a `query_docs` tool that lets you ask questions against Cortex's own documentation and knowledge base in natural language

## Cortex MCP overview

More of a visual learner? Watch the Cortex MCP in action in this short video.

{% embed url="<https://www.youtube.com/watch?v=Tjm6nwO4ByQ>" %}


# Configuring the Cortex MCP

You can host the MCP server locally, or you can use a remote implementation.

## Prerequisites

The following are required prior to configuring the Cortex MCP:

1. Ensure that you have a compatible MCP client installed, such as [Claude Desktop](https://claude.ai/download), [Jetbrains AI Assistant](https://www.jetbrains.com/help/ai-assistant/configure-an-mcp-server.html), or [Visual Studio Code (VSCode)](https://code.visualstudio.com/docs/copilot/chat/mcp-servers). Paid subscriptions to MCP clients generally give you a larger context window, but the free versions of these clients should suffice.
2. If hosting the MCP server locally, [Docker](https://www.docker.com/) must be installed and running.
3. Create a personal access token in Cortex. See [Creating personal access tokens](/configure/settings/api-keys/personal-tokens).

## Configuring the Cortex MCP

Follow the steps below to configure the Cortex MCP.

### Hosting the Cortex MCP server locally

Follow the steps below if the MCP server is hosted locally.

#### Step 1: Installing the Cortex MCP

Open terminal and run the following command:

```bash
docker pull ghcr.io/cortexapps/cortex-mcp:latest
```

#### Step 2: Configuring your MCP client

{% hint style="info" %}
Looking for IDE-specific setup? See the [README](https://github.com/cortexapps/cortex-mcp?tab=readme-ov-file#installation)
{% endhint %}

Update your MCP client's configuration file. Make sure to include your Cortex personal access token value for the `CORTEX_API_TOKEN` argument:

```json
{
  "mcpServers": {
    "cortex": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "--pull",
        "always",
        "-i",
        "--env",
        "CORTEX_API_TOKEN=YOUR_PERSONAL_ACCESS_TOKEN_HERE",
        "ghcr.io/cortexapps/cortex-mcp:latest"
      ]
    }
  }
}
```

**Alternate option: Create and configure the file in terminal**

Alternatively, you could enter the following in terminal to create and configure the file:

```
export CORTEX_API_TOKEN=VALUE_OF_YOUR_PERSONAL_ACCESS_TOKEN
cat << EOF > ~/Library/Application\ Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "cortex": {
      "command": "docker",
      "args": [
        "run",
        "--pull",
        "always",
        "--rm",
        "-i",
        "--env",
        "CORTEX_API_TOKEN=${CORTEX_ACCESS_TOKEN}",
        "ghcr.io/cortexapps/cortex-mcp:latest"
      ]
    }
 }
}
EOF
```

#### Step 3: Restarting your MCP client

After updating your configuration, restart your MCP client.

### Hosting the Cortex MCP server remotely

The remote Cortex MCP uses the public `cortex-mcp` package as a dependency, installed from GitHub. This configuration of the Cortex MCP enables:

* **Faster setup** - No need to install or maintain local binaries.
* **Updated context** - Cortex automatically keeps the service aligned with the latest MCP specification.
* **Secure access** - Tokens and access are managed in your Cortex workspace with security best practices.
* **Seamless integration** - It works out of the box with popular MCP clients like VSCode, Claude Code, and Cursor.
* **More tools** - The remote MCP implementation includes more tools, such as the `query_docs` tool that allows you to query Cortex's documentation and knowledge base in natural language. Ask questions like *How do I configure PagerDuty for my Cortex services?*, or *How can I use Cortex to drive AI maturity at my org?* It also includes the ability to add private tools and integrations on top of the public functionality.

#### Step 1: Adding the remote MCP server to your MCP client

Follow the instructions below for Claude, VSCode, or Cursor. Make sure to replace `<CORTEX_TOKEN>` with the value of the personal access token you generated in Cortex.

**Claude Code**

Run the following command to add the Cortex remote MCP server:

```
claude mcp add --transport http cortex-remote https://mcp.cortex.io/mcp --header "Authorization: Bearer <CORTEX_TOKEN>"
```

**VSCode**

Add the following configuration to your `.vscode/mcp.json` file:

```json
{
  "servers": {
    "cortex": {
      "url": "https://mcp.cortex.io/mcp",
      "type": "http",
      "headers": {
        "Authorization": "Bearer <CORTEX_TOKEN>"
      }
    }
  }
}
```

For more information, see the [official VSCode documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers).

**Cursor**

Add the following configuration to your Cursor settings:

```json
{
  "mcpServers": {
    "cortex": {
      "type": "http",
      "url": "https://mcp.cortex.io/mcp",
      "headers": {
        "Authorization": "Bearer <CORTEX_TOKEN>"
      }
    }
  }
}
```

#### Step 2: Validating your remote MCP configuration

Validate that your remote Cortex MCP is working:

* **VSCode** - Open the Command Palette and search for "MCP: List servers." Confirm that `cortex` appears as a connected server.
* **Claude** - Run the command `claude mcp list` and verify that cortex-remote is in the list of servers.
* **Cursor** - Open **Settings > MCP Servers** and verify that `cortex` is listed and connected.

#### Step 3: Restarting your MCP client

After updating your configuration, restart your MCP client.

### Self-managed additional configuration

If you are a [self-managed Cortex customer](/self-managed), you must also set `CORTEX_API_BASE_URL=https://` alongside the `CORTEX_API_TOKEN` variable.

**Self-managed configuration example**

Set the `CORTEX_API_BASE_URL` to your backend host URL:

```json
{
  "mcpServers": {
    "cortex": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "--pull",
        "always",
        "-i",
        "--env",
        "CORTEX_API_TOKEN=YOUR_ACCESS_TOKEN_HERE",
        "--env",
        "CORTEX_API_BASE_URL=https://api.cortex.company.com",
        "ghcr.io/cortexapps/cortex-mcp:latest"
      ]
    }
  }
}
```

If you are running a self-hosted instance with CA-signed certificates, you may need to mount them to the container as seen in the example below:

```json
{
  "mcpServers": {
    "cortex": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "--pull",
        "always",
        "-i",
        "-v",
        "/path/to/your//company_certs.ca:/etc/ssl/certs/company-ca.crt:ro",
        "--env",
        "REQUESTS_CA_BUNDLE=/etc/ssl/certs/company-ca.crt",
        "--env",
        "SSL_CERT_FILE=/etc/ssl/certs/company-ca.crt",
        "--env",
        "CURL_CA_BUNDLE=/etc/ssl/certs/company-ca.crt",
        "--env",
        "CORTEX_API_TOKEN=YOUR_ACCESS_TOKEN_HERE",
        "--env",
        "CORTEX_API_BASE_URL=https://api.cortex.company.com",
        "ghcr.io/cortexapps/cortex-mcp:latest"
      ]
    }
  }
}
```


# Using the Cortex MCP

This article explains how to use the Cortex MCP. For information on setting up the Cortex MCP, refer to [Configuring the Cortex MCP](/get-started/mcp/configuring-cortex-mcp).

{% hint style="success" %}
**We'd love your feedback!**\
If you're using the Cortex MCP, we'd love to hear your direct feedback on the configuration process, the tools available, and how you've been using it. Your feedback helps us improve and expand Cortex's capabilities. If you're interested in helping guide Cortex's MCP direction, [take the survey](https://forms.gle/yNLgLBrHTjKRJ34y5).
{% endhint %}

## Starting a new chat

In your MCP client, ask a question about your Cortex workspace. The client uses the Cortex API to provide detailed answers based on your data.

**Examples**

* You might ask what's going on with a specific Scorecard. The MCP client responds with an overview, Scorecard structure information, a progress summary, and suggestions for next steps.

  <div align="left" data-with-frame="true"><figure><img src="/files/oSu5vTQw9dJmbNELDTID" alt="Screenshot 1 of MCP example conversation" width="375"><figcaption></figcaption></figure></div>
* You could ask about an entity's custom data. The MCP client responds with that entity's custom data and information about when it was created.

  <div align="left" data-with-frame="true"><figure><img src="/files/rYLI7x9Xqbu7MUg4PS3N" alt="Screenshot 2 of MCP example conversation" width="375"><figcaption></figcaption></figure></div>
* You could ask about an entity's dependencies. The MCP client responds with a list of incoming and outgoing dependencies.

  <div align="left" data-with-frame="true"><figure><img src="/files/qAcNNxI5IzVOoA4Fgm2O" alt="Screenshot 3 of MCP example conversation" width="375"><figcaption></figcaption></figure></div>

## Available MCP tools

The Cortex MCP can use the following [Cortex REST API](https://docs.cortex.io/api/) endpoints:

| [listInitiatives](/api/readme/initiatives#get-api-v1-initiatives)                                                     | [listAllEntities](/api/readme/catalog-entities#get-api-v1-catalog)                                      |
| --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| [getInitiative](/api/readme/initiatives#get-api-v1-initiatives-cid)                                                   | [listEntityDescriptors](/api/readme/catalog-entities#get-api-v1-catalog-descriptors)                    |
| [listRelationshipTypes](/api/readme/entity-relationship-types#get-api-v1-relationship-types)                          | [listDependenciesForEntity](/api/readme/dependencies#get-api-v1-catalog-callertag-dependencies)         |
| [getRelationshipTypeDetails](/api/readme/entity-relationship-types#get-api-v1-relationship-types-relationshiptypetag) | [getDependency](/api/readme/dependencies#get-api-v1-catalog-callertag-dependencies-calleetag)           |
| [listEntityRelationships](/api/readme/entity-relationships#get-api-v1-relationships-relationshiptypetag)              | [getEntityDetails](/api/readme/catalog-entities#get-api-v1-catalog-tagorid)                             |
| [listScorecards](/api/readme/scorecards#get-api-v1-scorecards)                                                        | [getCustomDataForEntity](/api/readme/custom-data#get-api-v1-catalog-tagorid-custom-data)                |
| [getScorecard](/api/readme/scorecards#get-api-v1-scorecards-tag)                                                      | [getCustomDataForEntityByKey](/api/readme/custom-data#get-api-v1-catalog-tagorid-custom-data-key)       |
| [getScorecardNextStepsForEntity](/api/readme/scorecards#get-api-v1-scorecards-tag-next-steps)                         | [getCurrentOncallForEntity](/api/readme/on-call#get-api-v1-catalog-tagorid-integrations-oncall-current) |
| [listScorecardScores](/api/readme/scorecards#get-api-v1-scorecards-tag-scores)                                        | [getEntityDescriptor](/api/readme/catalog-entities#get-api-v1-catalog-tagorid-openapi)                  |

**Additional tools**

**getMyWorkspace** - Enabled by default, this tool supports the "Mine" capabilities that are available in the Cortex UI. Ask questions like, *Show me my Cortex entities* or *Tell me how my entities are performing against the Production Readiness Scorecard.*

### Enabling and disabling provided tools

Before submitting questions or commands, you may want to limit the number of provided tools being used by the MCP provider. For example, you might want to use the MCP to ask about entities, but you don't want to allow questions about Scorecards.

**Example**

In the settings of your MCP client, it's possible to limit which Cortex tools are being used. For example, in Claude desktop:

1. Navigate to **Settings > Connectors > Cortex > 3 dots icon > Tools and Settings**.
2. Below **Provided Tools**, toggle off the options you don't need.
3. Restart Claude.
4. Navigate to your Claude chat and enter commands.

## Eng Intelligence metrics in the Cortex MCP

[Eng Intelligence](/improve/eng-intelligence) metrics are also available to Cortex MCP. This brings metric data directly into the Cortex MCP, enabling richer AI-assisted insights, not only into engineering performance, but across your entire Cortex ecosystem. It allows you to be a more proactive leader and enables more data-driven planning sessions.

### Querying Eng Intelligence metrics in the Cortex MCP

Ensure you have the latest Cortex MCP version configured in your environment. Once enabled, the MCP automatically includes endpoints for Eng Intelligence metrics. You can then query Eng Intelligence metrics alongside ownership, Scorecard, and Initiative information. For example:

* *Evaluate my DORA metric performance in Q3. Highlight where the team is performing well and bring areas of improvement to my attention.*
* *Which services have concerning MTTR trends, and what scorecard gaps are contributing?*
* *Recommend initiatives and scorecard changes I could consider to address my upward trend in incidents.*
* *Review last quarter’s performance against our goals, identify the top three bottlenecks, and suggest changes to our scorecards to address them.*
* *Is there a correlation between my PR size and how fast we ship?*

## Crafting effective MCP prompts

The Cortex MCP becomes more powerful when using it becomes second nature to your teams. That shift happens when you have developed prompts that fit your specific role, answer your recurring questions, and surface information in the exact moments you need it. Refer to the [Cortex MCP Prompt Library](/get-started/library) for more information.

## Troubleshooting and FAQ

See frequently asked questions below.

**When I ask a question in my MCP client, why do I see an error that says I hit the max length for this chat?**

This can happen if you're on the free plan of your MCP client.

**Can I make changes via the Cortex MCP?**

No, you cannot make changes or write data via the Cortex MCP. The MCP is strictly read-only—it only handles `GET` requests and cannot modify or write data.

**How do I resolve "unauthorized" errors in the MCP?**

Ensure the value of your Cortex API token is valid in your configuration.

**How do I resolve "file not found" errors in the MCP?**

Ensure your OpenAPI spec path is correct when mounting.

**How do I resolve connection issues with the MCP?**

Verify your Cortex API endpoint is accessible.

**How do I resolve a 403 forbidden error in the remote MCP?**

Ensure that you set up the remote MCP with a [personal access token](/configure/settings/api-keys/personal-tokens) generated in Cortex. Remote MCP setup requires a personal access token, not an API key.

**Why do I see an SSL certificate error while using the MCP?**

This is most likely caused by an issue within your network. It's recommended to contact your organization's infrastructure or security team to troubleshoot.


# Ingesting data into Cortex

Bringing your data into Cortex unlocks everything else the platform can do. It's the foundation for data-driven decisions, clearer accountability, and a shared understanding of how your engineering organization actually works.\
\
Once your services, repositories, teams, and infrastructure are connected, Cortex stitches it all into a complete, always-current view of your ecosystem. That view is what makes it possible to track ownership, enforce production readiness through Scorecards, standardize common developer Workflows, and give every engineer the context they need to find what they're looking for, see how the pieces fit together, and make better decisions at every stage of the development lifecycle.

## How Cortex handles data modeling

Cortex is built to mirror how your organization actually works. You get the flexibility to model your business logic across your data, and the structure to make sure that logic stays consistent everywhere it appears so your workspace reflects reality instead of forcing your team to work around it.

Cortex solves for this by giving you the flexibility to mirror your unique business logic across your data, and the structure to persist that logic everywhere:

* **Foundational, configurable data models**. A strong starting point you can shape to fit your environment.
* **Available, extensible integrations**. Connect the tools you already use, and extend them as your needs grow.
* **Complete, customizable experience**. A polished workspace out of the box, ready to be tailored to your team.

**The result**: a consistent developer workflow and an experience built around how your organization actually operates, making it easier to represent your services and infrastructure accurately in Cortex.

See an [overview of Cortex data concepts below](#cortex-data-concepts-reference-table).

{% hint style="success" %}
**Need assistance with data modeling?**\
To ensure a smooth implementation, most of our customers partner with Cortex Professional Services (PS) for hands-on assistance, including expert guidance on data modeling. Contact <help@cortex.io> to learn more.
{% endhint %}

## Connecting your data

Connecting your data in Cortex comes down to three building blocks: **entities**, **catalogs**, and **integrations**. Together, they determine what lives in your workspace and how it stays accurate over time.\
\
[Entities](/ingesting-data-into-cortex/entities-overview/entities) are the foundation. An entity is an object that represents a software construct such as a service, a piece of infrastructure, a team, or anything else worth tracking. Entities are defined in YAML, can pull in data from your integrations, can have dependencies, can be organized into hierarchies, and can connect to other entities through entity relationships. You can also enforce standards across them using Scorecards.\
\
[Catalogs](/ingesting-data-into-cortex/catalogs) are how you organize entities into meaningful groups. A catalog is a defined selection of entities used to track and store information about the components that make up your infrastructure.\
\
[Integrations](/ingesting-data-into-cortex/integrations) are how the data flows in. Cortex supports a broad set of integrations that pull live data from the tools your team already uses, creating a single pane of glass across your engineering ecosystem.

{% hint style="success" %}
Want to learn more? Check out the Cortex Academy course on [Catalogs, Entities, and Relationships](https://academy.cortex.io/courses/understanding-understanding-catalogs-entities-and-relationships).
{% endhint %}

## Cortex data concepts reference table

Learn about the basic data concepts for Cortex below.

<table><thead><tr><th width="158.5728759765625">Concept</th><th width="548.3333129882812">Definition</th></tr></thead><tbody><tr><td><strong>Team</strong></td><td>A group of humans responsible for something</td></tr><tr><td><strong>Service</strong></td><td>A running technical component (API, job, infra service)</td></tr><tr><td><strong>Domain</strong></td><td>A foundational grouping layer that represents a logical or functional area of your organization. Domains form the base hierarchy that organizes entities under stable, high-level boundaries. Each domain reflects a cohesive area of ownership, business function, or technical responsibility.</td></tr><tr><td><strong>Custom entity</strong></td><td>Any other trackable thing - ML models, Clients, environment, release, Products. Use this when "service" doesn't fit.</td></tr><tr><td><strong>Catalog</strong></td><td>A folder-like visual container, for UI organization only</td></tr><tr><td><strong>Group</strong></td><td>A logical collection for search, filtering, and reporting—similar to a label or tag</td></tr><tr><td><strong>Dependency</strong></td><td>One entity relies on another; enables impact analysis and notifications</td></tr><tr><td><strong>Ownership</strong></td><td>The accountability link between a team and entity</td></tr><tr><td><strong>Entity relationship</strong></td><td>The generic link between entities</td></tr><tr><td><strong>Hierarchy</strong></td><td>Parent-child or part-of structure; enables inheritance ownership</td></tr></tbody></table>


# Entities overview

Entities are the foundational building blocks for representing your software ecosystem. Each entity models a distinct software construct—like a service, library, or team—giving your organization a shared, structured way to describe what exists and how it fits together. A defined collection of entities forms a [catalog](/ingesting-data-into-cortex/catalogs): a single source of truth that everyone, from engineers to leadership, can rely on.

Entities are designed to be both flexible and interconnected. They're defined in YAML so they're portable and version-controlled, enriched through integrations that pull in live data from the tools you already use, and measured against standards through Scorecards to drive quality and consistency over time.

Every entity has a dedicated page that brings its data together in one place, making it easy to understand context, ownership, and health at a glance. See [Entity details](/ingesting-data-into-cortex/entities-overview/entities/details) for more information.

{% hint style="success" %}
Want to learn more? Check out the Cortex Academy course on [Catalogs, Entities, and Relationships](https://academy.cortex.io/courses/understanding-understanding-catalogs-entities-and-relationships).
{% endhint %}

## Catalog and entities overview video

The video below shows how Cortex catalogs your engineering assets to improve visibility, adoption, and productivity:

{% embed url="<https://www.youtube.com/watch?v=A5w6ebxGbeg>" %}

## Entity types

Choose from the default entity types or [define your own](#custom-entity-types).

### **Default entity types**

Cortex provides a set of built-in entity types that cover the most common building blocks of a software organization. These defaults give you a strong foundation out of the box, so you can start cataloging your ecosystem without needing to design a schema from scratch.

<table><thead><tr><th width="158.5">Entity type</th><th>Purpose</th><th>Typical use</th></tr></thead><tbody><tr><td><strong>Services</strong></td><td>Represent codebase-like modules</td><td>Microservices, libraries, components</td></tr><tr><td><strong>Domains</strong></td><td>Group entities into logical units</td><td>Product areas, business capabilities, system boundaries</td></tr><tr><td><strong>Teams</strong></td><td>Represent the 'people side' of your catalog</td><td>Ownership, membership, contact info</td></tr><tr><td><strong>Cloud resources</strong></td><td>Sync infrastructure into your catalog</td><td>AWS, Azure, and Google Cloud resources</td></tr></tbody></table>

**Services** are the core of your catalog and the default entity type. Use them to represent any codebase-like module, e.g. microservices, libraries, components, and similar building blocks. Services are typically where the majority of your catalog activity happens, since they connect to code, deployments, ownership, and quality standards. See [Add services](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services).

**Domains** let you group services, resources, and other domains into hierarchical, logical units. They're useful for modeling how your organization actually thinks about its software—by product area, business capability, or system boundary—and for rolling up insights across related entities. See [Add domains](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/domains).

**Teams** represent the people side of your catalog. Use them to capture team membership, ownership relationships, and contact information, so it's always clear who's responsible for what. See [Add teams](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams).

**Cloud resources** can be pulled in directly from your cloud providers and represented as their corresponding entity types, keeping your catalog in sync with what's actually running in your infrastructure:

* For **AWS**, choose which resource types to include in your [AWS integration settings](https://app.getcortexapp.com/admin/settings/aws?activeTab=settings).
* For **Azure**, choose which resource types to include in your [Azure Resources integration settings](https://app.getcortexapp.com/admin/settings/azureresources).
* For **Google Cloud**, see the list of [supported entity types](/ingesting-data-into-cortex/integrations/google#supported-google-entity-types).

### **Custom entity types**

While Cortex's built-in entity types cover most common needs, every organization has its own way of modeling its software ecosystem. Custom entity types let you extend your catalog to reflect the concepts that matter to your teams, whether that's APIs, data pipelines, ML models, or anything else you want to track.

You can create unlimited custom entity types through the Cortex UI or API. Once a type is defined, you can begin adding entities of that type using the UI, API, or GitOps, just like you would with built-in types.

See [Add custom entity types](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/entity-types) for more information.


# Managing entities

This article provides an overview of how to manage entities in Cortex. For an overview of how entities work, see [Entities overview](/ingesting-data-into-cortex/entities-overview).

## Adjusting general settings for entities

Admins and users with the `Configure Settings` permission can adjust system-wide settings for entities under **Settings > Entities > General.** See [Entity settings](/configure/settings/entity-settings).

## Defining entities with YAML

Every entity in your Cortex catalog is defined by a YAML file known as the Cortex entity descriptor (or *Cortex YAML*, named after the `cortex.yaml` file used in the [GitOps approach](#managing-entities-via-gitops)). This applies whether you manage entities through the UI or GitOps—the descriptor is the underlying source of truth either way.

You can extend an entity by adding metadata to the `info` section of its descriptor. Throughout the docs, you'll see snippets prefixed with `x-cortex-*`; these are descriptor blocks that belong inside `info` and unlock additional Cortex functionality.

See [Defining entities with YAML](/ingesting-data-into-cortex/entities-overview/entities/yaml) for more information.

## Unique identifiers for entities

### **Cortex tag**

The Cortex tag (formerly the *entity tag*) is a customizable, unique identifier used to reference an entity throughout Cortex. It's defined by the `x-cortex-tag` value in an entity's YAML file and powers core functionality like declaring dependencies between entities or looking up information through the [Cortex AI Assistant](/get-started/cortex-ai-assistant).

Each Cortex tag must be globally unique across all entities in your workspace.

**Changing a Cortex tag**

Editing an entity's `x-cortex-tag` doesn't rename the existing entity, it creates a new one. Cortex generates a new entity with the updated tag and leaves the original entity untouched, regardless of whether the change is made through the UI editor, the API, or GitOps. Both entities continue to exist in your catalog until you archive or delete the original.

**Reusing a Cortex tag**

A Cortex tag can only be associated with one entity at a time. To reuse a tag that's already in use, the entity currently holding it must be [archived](/ingesting-data-into-cortex/entities-overview/entities/archiving-entities) first.

### **Cortex ID**

The Cortex ID (CID) is a unique, immutable identifier assigned to every entity in Cortex. Unlike the Cortex tag, which you define and can change, the CID is automatically generated, fixed for the life of the entity, and 18 characters long, making it ideal for historical tracking, reporting, and any system of record outside of Cortex.

You can use the CID anywhere you'd reference an entity: in the API, in CQL queries, throughout the app, and with the Cortex AI Assistant.

**Where to find the CID**

The CID appears in an entity's URL and at the top of its entity page. It doesn't appear in the entity's YAML file, since it can't be modified.

<div align="left" data-with-frame="true"><figure><img src="/files/Ah50yX6uLLpk12UU5mPu" alt="The CID in the URL and on the entity&#x27;s details page." width="563"><figcaption></figcaption></figure></div>

## Managing entities via GitOps

Accounts are configured to edit entities through the UI by default. It's strongly recommended to start with the UI editor, which includes a built-in YAML editor, then moving to GitOps when you're ready to scale.

Follow the steps below to enforce GitOps-only creation and editing of entities.

1. From the main sidebar, click your avatar in the bottom-left corner.
2. Click **Settings**.
3. From the **Settings** menu, locate the **Workspace** section, then click **GitOps**.
4. From the **Entities** tab, scroll to **Options by entity type**.
5. Do the following:
   1. To only allow editing of entities via GitOps, toggle off **Enable UI editing for new entity types**.
   2. To only allow creation of entities via GitOps, toggle off **Enable UI importing for new entities**.
   3. To override these settings for a specific entity type, disable the **UI editing** and **UI importing** toggles next to that type in the list. This enforces a GitOps-only approach for that entity type.<br>

      <div align="left" data-with-frame="true"><figure><img src="/files/DPqabYfNPJZDXHKJTlNk" alt="Entity types list with UI editing and UI importing toggles disabled for a selected type." width="375"><figcaption></figcaption></figure></div>

#### Things to keep in mind when using GitOps

When using GitOps, you can define any number of entities in any repository.

* Domain definitions should live in the `.cortex/domains` directory in your repository.
* Team definitions should live in the `.cortex/teams` directory in your repository.

Entity definitions can live in one central repository, or alongside the service they describe in that service's own repository.

See the single repository example below:

```
.
└── .cortex
    ├── catalog
    │   ├── database.yml
    │   ├── s3-bucket.yml
    │   ├── auth-service.yml
    │   └── billing-service.yml
    ├── domains
    │   ├── billing-domain.yml
    │   └── health-domain.yml
    ├── teams
    │   ├── eng-team.yml
    │   └── sre-team.yml
```

See [Using GitOps for Cortex](/configure/gitops) for more information.

## Adding entities to catalogs

Each catalog has entity type criteria that determine which entities it includes. When an entity is created or imported, it's automatically added to any catalog whose criteria it meets. You set these criteria when [creating a custom catalog](/ingesting-data-into-cortex/catalogs#custom-catalogs).

Default catalogs have their entity type criteria set automatically:

* The **Services** catalog contains `service` entity types
* The **Domains** catalog contains `domain` entity types
* The **Teams** catalog contains `team` entity types
* The **Infrastructure** catalog contains any entities that are *not* the types `service`, `domain`, or `team`.
  * Its catalog filter is set to exclude the types `service`, `domain`, and `team`:<br>

    <div align="left" data-with-frame="true"><figure><img src="/files/Gt5XhNkFATrVeCgR7BeU" alt="Image of an entity&#x27;s catalog filter." width="301"><figcaption></figcaption></figure></div>
  * By default, any [custom entity types](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/entity-types) you create belong to the Infrastructure catalog. If you don't want an entity type to belong to this catalog, you can add the entity type to a different catalog.

To learn more about adding each type of entity to Cortex, see:

* [Add services](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services)
* [Add domains](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/domains)
* [Add teams](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams)
* [Add custom entity types](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/entity-types)

### Managing entities across catalogs

The **All entities** page lists every entity that's been imported into Cortex, regardless of type. To open it, expand **Catalogs** in the main sidebar and select **All entities**. The page opens to the **Mine** tab if you own any entities, and defaults to the **All entities** tab otherwise.

Each row shows the entity's name and tag. Most workspaces start with just a few dozen entities, but catalogs often grow to hundreds (or thousands!) of entities over time as more of your ecosystem is brought into Cortex.

#### Searching across and filtering entities

<div align="left" data-with-frame="true"><figure><img src="/files/yzzZwYpmndcKzmOTWaan" alt="The search and filter options in the upper-right corner of the page." width="563"><figcaption></figcaption></figure></div>

There are several ways to search and filter your entities list.

1. From the main sidebar, expand **Catalogs**, then select **All entities.**
2. Do one of the following:
   * Select the **All** tab to search and filter across all of your organization's entities.
   * Select the **Mine** tab to search and filter only the entities you own.
3. Do any or all of the following:
   * To find specific entities, use the search bar in the upper-right corner of the entities list and type to search.
   * Click **Name** to select whether you want to sort by name or identifier, and whether to sort by ascending or descending order.
   * Click **Display** to choose whether to show archived entities in the list, and select which columns to display alongside entities.
     * **Incidents** - Displays how many active incidents are associated with a given entity. This information is pulled from FireHydrant, incident.io, PagerDuty, and Rootly.
     * **Health** - When you click into this column in an entity's row, you can view more information about:
       * **Monitors** - Shows how entities are performing against monitors you’ve created in your APM. When an entity is passing all monitors, this cell will display `All OK`; otherwise, it displays `Failing`, `Warning`, or `No Data`, along with how many monitors the entity is not hitting. This information is pulled from Datadog.
       * **Error rate** - Shows the percentage of transactions that result in a failure during a pre-specified window. This information is pulled from New Relic.
       * **Apdex (Application Performance Index)** - Ratio of the number of satisfied and tolerating requests to the total number requests made. This information is pulled from New Relic.<br>

         <div align="left" data-with-frame="true"><figure><img src="/files/9uAkJtwfj7iG0vPclWjs" alt="Shows the health and incidents columns on the entities page." width="304"><figcaption></figcaption></figure></div>
     * Columns that rely on an integration display **Not connected** when the integration hasn't been set up. If the integration is connected but the entity has no associated data or configuration, the cell displays **None** instead.
   * Click **Filter** to narrow down your list by associated Git repository, unowned entities, AWS account ID or region, domain, entity type, group, team, or user.

#### Viewing entity types

Select the **Entity types** tab to view all entity types in your workspace. Click any entity type to see more details about it.

<div align="left" data-with-frame="true"><figure><img src="/files/S983moTAqbQUZqwfL6Zr" alt="The &#x27;Entity types&#x27; tab shows all entity types in your organization." width="563"><figcaption></figcaption></figure></div>

Built-in entity types are marked with a Cortex logo. Hover over the logo to see a "Powered by Cortex" banner. Any other types in the list are custom entity types created for your workspace. To learn more about creating your own, see [Add custom entity types](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/entity-types).

<div align="left" data-with-frame="true"><figure><img src="/files/B6MeZaglbUSl9Rde7d96" alt="" width="278"><figcaption></figcaption></figure></div>

#### Changing an entity's type

Entities can be reclassified to a different type as their role in your catalog evolves. For example, an entity originally created as a service could later be changed to a domain. This gives you flexibility to restructure your catalog as your organization changes—useful when entities were initially imported under the wrong type, or when you want to consolidate, split, or rethink how parts of your ecosystem are modeled.&#x20;

Admins or users with the `Configure Settings` permission can change an entity's type.

**Prerequisites**

1. Toggle on the option to change an entity type:
   1. From the main sidebar, click your avatar in the bottom-left corner.
   2. Click **Settings**.
   3. From the **Settings** menu, locate the **Workspace** section, then click **Entities**.
   4. Click **General**.
   5. In the **Entity settings** section, toggle on **Enable changing entity type**.

{% hint style="info" %}
If you'd rather keep entity types fixed after creation, keep this option toggled off to enforce stability across your catalog.
{% endhint %}

**To change an entity's type**:

{% hint style="warning" %}
Changing an entity's type could result in broken dependencies and hierarchies.
{% endhint %}

Update the entity YAML. Change the `x-cortex-type` field in the entity's YAML descriptor to the new type. This can only be done via YAML, not through the UI.

A **Cannot change the type of the entity** error means the **Enable changing entity type** option is disabled. Turn it on to allow the change. See the prerequisite section above.

{% hint style="info" %}
Deleted entities can be re-created with a different type, regardless of this setting.
{% endhint %}

#### Viewing relationship types

Software ecosystems are rarely flat. Services depend on each other, teams own different parts of the stack, and domains nest inside larger business areas. Relationship types let you capture these connections in Cortex, so your catalog reflects how your organization actually fits together.

A relationship type defines how two entities relate to one another and which entity types are allowed as the source and destination of that relationship. Cortex supports a few different ways to model these connections:

* **Entity relationships** - Custom relationships you define between any entity types, either hierarchical or cyclical.
* **Team hierarchies** - Hierarchical relationships between team entities, including ownership over other entities.
* **Domain hierarchies** - Hierarchical relationships between domain entities, with optional ownership inheritance from higher levels of the hierarchy.
* **Dependencies** - Cyclical relationships between non-team entities, used to model how services and resources rely on each other.

Together, these relationship types give you a flexible way to represent both the structural and operational connections across your workspace.&#x20;

To view all relationship types, expand **Catalogs** in the main sidebar and select **All entities**. Select the **Relationship types** tab.

<div align="left" data-with-frame="true"><figure><img src="/files/s7cIjPOsjfWXWK2WDCRe" alt="&#x27;Relationship types&#x27; tab in Cortex showing the list of defined entity relationships" width="563"><figcaption></figcaption></figure></div>

See [Defining relationship types](/ingesting-data-into-cortex/entities-overview/entities/defining-relationship-types) for more information.

## Archiving entities

Entities can be deleted outright, but archiving is often the better choice as it removes entities from active use while preserving them for historical reference.

For hands-off maintenance, [configure auto-archival](/configure/settings/entity-settings/auto-archive) to automatically archive entities when they're no longer detected in your integrations or when their YAML files are deleted. Entities can also be archived manually through the Cortex UI or API. See [Archiving entities](/ingesting-data-into-cortex/entities-overview/entities/archiving-entities).


# Defining entities with YAML

Every entity in your Cortex catalog is defined by a YAML file called the Cortex entity descriptor—often referred to as an entity's *Cortex YAML*, after the `cortex.yaml` filename used in the GitOps approach. This applies whether you manage entities through the UI or GitOps; the descriptor is the underlying source of truth either way.

Each descriptor is a fully compliant OpenAPI 3 spec file, extended with Cortex-specific fields that unlock additional functionality in your catalog.

{% hint style="info" %}
You don't need to use OpenAPI or Swagger to use Cortex. The OpenAPI spec serves as the foundation for entity metadata because it's an open standard with official support for extensions, allowing Cortex to extend it into a full entity descriptor spec, while keeping the actual OpenAPI fields optional.
{% endhint %}

## Metadata in entity descriptor YAML files

You can extend an entity by adding metadata to the `info` section of its descriptor. Throughout the docs, you'll see snippets prefixed with `x-cortex-*`; these are descriptor blocks that belong inside `info` and unlock additional Cortex functionality.

{% hint style="info" %}
YAML comments aren't supported in entity descriptors. Cortex stores descriptors as JSON in the database, and JSON doesn't support comments. Most YAML parsers also strip comments during round-tripping, so any comments added to a descriptor will be lost.
{% endhint %}

### Required blocks

Every entity YAML requires the following:

<table><thead><tr><th width="180.3828125">Block</th><th>Description</th></tr></thead><tbody><tr><td><code>title</code></td><td>The name of the entity</td></tr><tr><td><code>x-cortex-tag</code></td><td>The <a href="#entity-tag">unique identifier for the entity</a></td></tr><tr><td><code>x-cortex-type</code></td><td><p>The <a href="#entity-types">entity type</a><br></p><ul><li>If the entity is a <a href="/pages/0BEkeCNaXgSo20PlGcRo#create-custom-entities-in-the-entity-descriptor">custom type</a>, you must also include <code>x-cortex-definition</code></li></ul></td></tr></tbody></table>

### **Recommended blocks**

Although they aren't required, it's strongly recommended to add a description, groups, and owners:

<table><thead><tr><th width="180.3984375">Block</th><th>Definition</th></tr></thead><tbody><tr><td><code>description</code></td><td>A description of the entity</td></tr><tr><td><code>x-cortex-groups</code></td><td><p>The entity's <a href="/pages/ruG8CemqPJPUPiLhd1o8">groups</a> - a tagging system used to segment entities<br></p><ul><li>Required field - <code>tag</code></li></ul></td></tr><tr><td><code>x-cortex-owners</code></td><td><p>The entity's <a href="/pages/3sA3UzKYpba4iDmzT7Gj">owners</a><br></p><ul><li>Required field - <code>type</code></li><li>Owners can be defined by <code>group</code> from an <a href="/pages/3sA3UzKYpba4iDmzT7Gj#entity-descriptor">ownership integration</a> or by email address</li><li><code>inheritance</code> - When creating a domain entity and adding owners to it, or while creating an entity relationship, you can set <a href="/pages/3sA3UzKYpba4iDmzT7Gj#ownership-inheritance">ownership inheritance</a> under this block to pass down to the entity's children. The inheritance type can be <code>APPEND</code>, <code>FALLBACK</code>, or <code>NONE</code>.</li></ul></td></tr></tbody></table>

### **Additional basic metadata blocks**

<table><thead><tr><th width="179.90625">Block</th><th>Definition</th></tr></thead><tbody><tr><td><code>x-cortex-custom-metadata</code>:</td><td><p>The entity's <a href="/pages/0pawHMQrFlZ2APpwlqa3">custom data</a><br></p><ul><li>Required fields - a key, <code>value</code>, and <code>description</code>. The key is the title for the custom data.</li></ul></td></tr><tr><td><code>x-cortex-dependency</code></td><td><p>The entity's <a href="/pages/lriEpowNUcQfWez9QDDX">dependencies</a><br></p><ul><li>Required fields - <code>tag</code>. If <code>method</code> is included, then <code>path</code> is also required.</li></ul></td></tr><tr><td><code>x-cortex-link</code></td><td><a href="/pages/5cEJd1jQZq1Shqjz7YAg">Documentation links</a> associated with the entity: <code>name</code>, <code>type</code>, and <code>url</code></td></tr><tr><td><code>x-cortex-parents</code> and <code>x-cortex-children</code></td><td><p>The entity's parent entities and children entities<br></p><ul><li>Required field - <code>tag</code></li><li>These fields are supported for entities that are members of a <a href="/pages/PVRYqXSfutvMjgCZhp3F#understanding-relationship-types-in-cortex">hierarchical entity relationship</a>, such as domains or teams</li></ul></td></tr><tr><td><code>x-cortex-relationships</code></td><td><p>A block that includes the entity's <a href="/pages/PVRYqXSfutvMjgCZhp3F#entity-descriptor">relationship type and destination entities</a><br></p><ul><li>Required fields - <code>type</code> and <code>destinations</code></li></ul></td></tr><tr><td><code>x-cortex-team</code></td><td><p>This appears in a <a href="/pages/k2dYsILMpH9zFdKGLhRj#entity-descriptor">team entity's YAML</a>. <code>members</code> can be defined under this block.<br></p><ul><li>A <code>member</code> is defined by <code>name</code> and <code>email</code>, and can also include <code>notificationsEnabled</code> and <code>roles</code>.</li></ul></td></tr></tbody></table>

### **Integration metadata blocks**

See the related linked documentation pages for instructions on adding metadata within each type of block.

<table><thead><tr><th width="299.6015625">Block</th><th></th></tr></thead><tbody><tr><td><code>x-cortex-alerts</code></td><td><a href="/pages/JEvChnD825Dk6Byn1mog">Opsgenie</a></td></tr><tr><td><code>x-cortex-apiiro</code></td><td><a href="/pages/rKjGunK2MAdxgaELbtSW">Apiiro</a></td></tr><tr><td><code>x-cortex-apm</code></td><td><a href="/pages/kRWtggFQYYp6FS6DzgLk">Datadog</a>, <a href="/pages/uOMTxgC5zj2oFsWsoXcq">Dynatrace</a>, <a href="/pages/3J3rOtgnvKCFiglcfy1O">New Relic</a></td></tr><tr><td><code>x-cortex-azure</code></td><td><a href="/pages/dLCbw5E6LxK8D3yCJCYD">Azure Resources</a></td></tr><tr><td><code>x-cortex-azure-devops</code></td><td><a href="/pages/UfaVrLl3RKIMq5MfGl8t">Azure DevOps</a></td></tr><tr><td><code>x-cortex-bugsnag</code></td><td><a href="/pages/o8Lte9uCwNidfXDXdtAc">BugSnag</a></td></tr><tr><td><code>x-cortex-ci-cd</code></td><td><a href="/pages/jGrBfRxtPPcGz3DNdZcs">Buildkite</a></td></tr><tr><td><code>x-cortex-checkmarx</code></td><td><a href="/pages/YApHGr8JiWQIwelMxuA7">Checkmarx</a></td></tr><tr><td><code>x-cortex-circle-ci</code></td><td><a href="/pages/SAZ8GgdTpdVOKEuuP3kU">CircleCI</a></td></tr><tr><td><code>x-cortex-coralogix</code></td><td><a href="/pages/B4Sw6S0xL3yKUhs5flhn">Coralogix</a></td></tr><tr><td><code>x-cortex-dashboards</code></td><td>Charts embedded from <a href="/pages/kRWtggFQYYp6FS6DzgLk">Datadog</a>, <a href="/pages/wc7RqyD55GDSaxYUmu8f">Grafana</a>, or <a href="/pages/3J3rOtgnvKCFiglcfy1O">New Relic</a></td></tr><tr><td><code>x-cortex-firehydrant</code></td><td><a href="/pages/rxkq9NIP59CbOPbVOe7p">FireHydrant</a></td></tr><tr><td><code>x-cortex-git</code></td><td><a href="/pages/UfaVrLl3RKIMq5MfGl8t">Azure DevOps</a>, <a href="/pages/kGrYUNlQZ02lIZkLr9GB">Bitbucket</a>, <a href="/pages/Xk8Sl5l7hncSwE0jkSC5">GitHub</a>, <a href="/pages/WW79Lsssh71ec7TlH7L2">GitLab</a></td></tr><tr><td><code>x-cortex-incident-io</code></td><td><a href="/pages/ZxMuzQi9AvvPGuN8njG5">incident.io</a></td></tr><tr><td><code>x-cortex-infra</code></td><td><a href="/pages/IpplVfBAjkvV30wggOAV">AWS</a>, <a href="/pages/lgZ9FTSqYCAkvTxVKYnR">Google</a></td></tr><tr><td><code>x-cortex-issues</code></td><td><a href="/pages/F0YEYLHAXU4ne0S0bb66">ClickUp</a>, <a href="/pages/Xk8Sl5l7hncSwE0jkSC5">GitHub</a>, <a href="/pages/hzJxJGhFlJtRBS9bw0ZM">Jira</a></td></tr><tr><td><code>x-cortex-k8s</code></td><td><a href="/pages/dLo7cW1bb9JvK7AJ9imS">Kubernetes</a></td></tr><tr><td><code>x-cortex-launch-darkly</code></td><td><a href="/pages/qCf8Um88KkPrjrn4hQSb">LaunchDarkly</a></td></tr><tr><td><code>x-cortex-microsoft-teams</code></td><td><a href="/pages/eA83dZvRK3iwWEE2NAJI">Microsoft Teams channels</a></td></tr><tr><td><code>x-cortex-oncall</code></td><td><a href="/pages/XDAUWFsDegInAZMY2ucB">PagerDuty</a>, <a href="/pages/uNmFSzHYVZklPYzhpikK">Splunk On-Call (VictorOps)</a>, <a href="/pages/sQYZHpisDx2OjQLnsP4A">xMatters</a></td></tr><tr><td><code>x-cortex-owners</code></td><td>When you specify <code>group</code> as the <code>type</code>, you can use the following integrations as the group <code>provider</code>: <a href="/pages/sezVtfvNGVEsZKLfOF2R">BambooHR</a>, <a href="/pages/kGrYUNlQZ02lIZkLr9GB">Bitbucket</a>, <a href="/pages/80JEbVo15jgcPcgvHwAZ">Entra ID (Azure AD)</a>, <a href="/pages/Xk8Sl5l7hncSwE0jkSC5">GitHub</a>, <a href="/pages/WW79Lsssh71ec7TlH7L2">GitLab</a>, <a href="/pages/lgZ9FTSqYCAkvTxVKYnR">Google</a>, <a href="/pages/jDIzrDn5NdqO33h6mzhy">Okta</a>, <a href="/pages/X7U6BovNifbqhXexFPxc">ServiceNow</a>, <a href="/pages/a13EpqM8gbXz8YVtYdvQ">Workday</a></td></tr><tr><td><code>x-cortex-rollbar</code></td><td><a href="/pages/ZHZIhHXr3KApkpZLigCU">Rollbar</a></td></tr><tr><td><code>x-cortex-rootly</code></td><td><a href="/pages/GmV26i9AeWtrz4VhaYwA">Rootly</a></td></tr><tr><td><code>x-cortex-sentry</code></td><td><a href="/pages/o0004rWtddFomLBsE48C">Sentry</a></td></tr><tr><td><code>x-cortex-semgrep</code></td><td><a href="/pages/HPYngZSFHEXMw12TF7I7">Semgrep</a></td></tr><tr><td><code>x-cortex-servicenow</code></td><td><a href="/pages/X7U6BovNifbqhXexFPxc">ServiceNow</a></td></tr><tr><td><code>x-cortex-slack</code></td><td><a href="/pages/E9axggeqAgqwSbjpIcUo">Slack channels</a></td></tr><tr><td><code>x-cortex-slos</code></td><td><a href="/pages/kRWtggFQYYp6FS6DzgLk">Datadog</a>, <a href="/pages/uOMTxgC5zj2oFsWsoXcq">Dynatrace</a>, <a href="/pages/lgZ9FTSqYCAkvTxVKYnR">Google</a>, <a href="/pages/RugXMwlZGeHNPfMTgavQ">Lightstep</a>, <a href="/pages/d5OW1jvVwAunmNp13nev">Prometheus</a>, <a href="/pages/YBtg2KsyFV3h411WSLOM">Splunk Observability Cloud (SignalFX)</a>, <a href="/pages/3MKMPLhBvPysG16IA7J3">Sumo Logic</a></td></tr><tr><td><code>x-cortex-snyk</code></td><td><a href="/pages/0dP78PbdmjrvRRBeFPsD">Snyk</a></td></tr><tr><td><code>x-cortex-static-analysis</code></td><td><a href="/pages/w9uMZxXgz3ZoMWzgiYXU">Codecov</a>, <a href="/pages/1Em0Q803ZImnzlIZfkxj">Mend</a>, <a href="/pages/LlpzID94xzZSAvmVKzFJ">SonarQube</a>, <a href="/pages/qgZciFiMo6NiLzGBjeW0">Veracode</a></td></tr><tr><td><code>x-cortex-wiz</code></td><td><a href="/pages/u7Q3UvY6KoFYL9TbRD8i">Wiz</a></td></tr></tbody></table>

## Example entity YAML

The example below demonstrates how you can use each of the blocks in an entity's YAML.

<pre class="language-yaml"><code class="lang-yaml">## API Spec and Version
openapi: 3.0.0

# Service Descriptors

# Required fields: info, title, x-cortex-tag
info:
  title: &#x3C;HUMAN_READABLE_SERVICE_NAME>
  x-cortex-tag: &#x3C;SERVICE_TAG>
   description: &#x3C;DESCRIPTION>

  # Groups
  # !Groups must contain only alphanumeric characters, and may not contain whitespaces!
  x-cortex-groups:
    - &#x3C;GROUP_NAME>
    - &#x3C;GROUP_NAME>
    - &#x3C;GROUP_NAME>
  
  # Owners
  x-cortex-owners:
    - type: group
      name: my-team
      provider: CORTEX # Use when referring to a team defined in Cortex; these teams do not map to identities from integrations
      description: This is a description for this owner
    - type: email
      email: user@example.com
      description: This is a description for this owner
    - type: group
      name: team-name
      provider: ACTIVE_DIRECTORY | AZURE_DEVOPS | BAMBOO_HR | GITHUB | GITLAB | GOOGLE | OKTA | OPSGENIE | SERVICE_NOW | WORKDAY
  # Also see the team entity example below
  
  # Links
  x-cortex-link:
     - name: &#x3C;HUMAN_READABLE_NAME>
       type: &#x3C;TYPE>
       url: &#x3C;URL_TO_LINK>
       description: &#x3C;DESCRIPTION>
  ## Note that type of OPENAPI/ASYNC_API will be displayed in the API Explorer tab in the Cortex UI
  ## Links support relative URLs

  # Dashboards
  x-cortex-dashboards:
   embeds:
     - type: &#x3C;datadog | grafana | newrelic>
       url: &#x3C;URL>

  # Custom Data
  x-cortex-custom-metadata:
     my-key: the value
     another-key:
       this: is
         an: object
     my-key-2:
       value: the actual value for the key
       description: This is the description
     final-key:
       - also
       - use
       - lists!
       
  # Custom entities
  # You cannot create a custom entity type via GitOps, but after creating the type in the UI or API, you can create custom entities via GitOps.
  title: Sally S
  description: Technical writer
  x-cortex-tag: employee-sally
  x-cortex-type: org-employees
  x-cortex-definition:
    location: San Diego
    department: Engineering

  # Parent and child relationships
  x-cortex-type: team
  x-cortex-children:
  - tag: child-team-1
  - tag: child-team-2
  
  x-cortex-type: domain
  x-cortex-parents:
  - tag: parent-team-1
  - tag: parent-team-2
  
  # Entity relationships
  x-cortex-relationships:
  - type: relationship-type-name
    destinations:
    - tag: destination-entity-1
    - tag: destination-entity-2
  

  # Dependencies
  # Required fields: x-cortex-tag, method (required if path present), path (required if method present)
  x-cortex-dependency:
       - tag: &#x3C;TAG>
         method: &#x3C;HTTP_METHOD>
         path: &#x3C;PATH_FOR_METHOD>
         description: &#x3C;DESCRIPTION>
         metadata:
           tags:
             - &#x3C;TAG_1>
             - &#x3C;TAG_2>
           prod: true
           
 # Team configurations
 title: Eng Team
 x-cortex-tag: eng-team
 x-cortex-type: team
 x-cortex-team:
   groups:
   - name: eng-team
     provider: OKTA
   members:
   - name: Eng Manager
     email: name@example.com
     notificationsEnabled: true 
   - name: Product Manager
     email: name@example.com
     notificationsEnabled: false
  x-cortex-children:
    - tag: infra-team
    - tag: sre-team
 
 # Domain configurations
   x-cortex-type: domain
   x-cortex-owners:
     - type: GROUP
       name: cortexapps/engineering
       provider: GITHUB
       interitance: APPEND | FALLBACK | NONE 
   x-cortex-children:
     - tag: chat-service
       tag: chat-database
       


  # Integrations
  
  # Apiiro
  x-cortex-apiiro:
    repositories:
      - alias: alias-one
        repositoryId: repository-one
      - alias: alias-two
        repositoryId: repository-two
    applications:
      - alias: alias-one
        applicationId: application-one
      - alias: alias-two
        applicationId: application-two
  
  # AWS Cloud Control types
  x-cortex-infra:
    aws:
      cloudControl:
      - type: AWS::RDS::DBInstance
        region: us-west-2
        accountId: "123456123456"
        identifier: rds-example
  
  # AWS ECS
  x-cortex-infra:
    aws:
      ecs:
        - clusterArn: &#x3C;CLUSTER_ARN>
          serviceArn: &#x3C;SERVICE_ARN>
        - clusterArn: &#x3C;CLUSTER_ARN_2>
          serviceArn: &#x3C;SERVICE_ARN_2>

  # Azure DevOps
  x-cortex-git:
    azure:
      project: &#x3C;project-name>
      repository: &#x3C;repository-name>
       
  # Azure Resources
  x-cortex-azure:
    ids:
    - id: /subscriptions/1fbb2da1-2ce7-45e4-b85f-676ab8e12345/resourceGroups/GROUP1/providers/Microsoft.Compute/disks/vm1_disk1_3d9f85717666435e9e87e4883d31a7e9
      alias: my-default-alias # alias is optional and only relevant if you have opted into multi account support
    - id: /subscriptions/1fbb2da1-2ce8-45e4-b85f-676ab8e12345/resourceGroups/GROUP2/providers/Microsoft.Compute/disks/vm1_disk1_3d9f85717666435e9e87e4883d31a7e0
      alias: my-other-alias # alias is optional and only relevant if you have opted into multi account support

  # BambooHR
  x-cortex-owners:
    - type: group
      name: &#x3C;TEAM_NAME>
      provider: BAMBOO_HR
      description: # optional

  # Bitbucket
  x-cortex-git:
    bitbucket:
      repository: &#x3C;workspace>/&#x3C;repo>
   x-cortex-owners:
       - type: group
         name: &#x3C;TEAM_NAME>
         provider: BITBUCKET
         description: # optional
         
  # Bugsnag
  x-cortex-bugsnag:
    project: &#x3C;PROJECT_KEY> # projectKey in Bugsnag
     
  # Buildkite
  x-cortex-ci-cd:
    buildkite:
      pipelines:
        - slug: my-buildkite-pipeline-slug-1
        - slug: my-buildkite-pipeline-slug-2
      tags:
        - tag: my-buildkite-tag-1
        - tag: my-buildkite-tag-2

  # Checkmarx
  x-cortex-checkmarx:
    projects:
      - projectName: My Cool Project
      - projectId: 1234
  
  # CircleCI
  x-cortex-circle-ci:
      projects:
      - projectSlug: circleci-projectslug # projectslug in CircleCI
        alias: circleci-alias # alias is optional and only relevant if you have opted into multi account support
  
  # ClickUp
  x-cortex-issues:
    clickup:
      spaces:
      - identifier: 123456789
        identifierType: ID
      folders:
      - identifier: my-folder
        identifierType: NAME
      tags:
      - name: tag a
      - name: tag b
  
  # Codecov
  x-cortex-static-analysis:
    codecov:
      owner: org-name
      repo: my-project
      provider: AZURE_DEVOPS | BITBUCKET | BITBUCKET_SERVER | GITHUB | GITHUB_ENTERPRISE | GITLAB | GITLAB_ENTERPRISE
      flag: flag

  # Coralogix
  x-cortex-coralogix:
    applications:
    - applicationName: my-app # application name tied to alert
      alias: my-alias # alias is optional and only relevant if you have opted into multi account support
  
  # Datadog
  x-cortex-apm:
    datadog:
      serviceTags: # List of tags &#x26; values
       - tag: &#x3C;KEY>
         value: &#x3C;VALUE>
       - tag: &#x3C;KEY>
         value: &#x3C;VALUE>
  .   serviceName: &#x3C;NAME IN DATADOG>
      monitors:
        - monitor-id
        - monitor-id-2
  x-cortex-slos:
     datadog: # List of SLO ids
       - id: slo-id-1
       - id: slo-id-1

  # Dynatrace
  x-cortex-apm:
    dynatrace:
      entityIds:
        - mock-service-id-1
        - mock-service-id-2
      entityNameMatchers:
        - "foo.*"
  x-cortex-slos:
    dynatrace:
      - id: slo-id-1
      - id: slo-id-2

  # Entra ID (Azure Active Directory)
  x-cortex-owners:
     - type: group
       name: &#x3C;TEAM_NAME>
       provider: ACTIVE_DIRECTORY
       description: # optional

  # FireHydrant
  x-cortex-firehydrant:
    services:
      - identifier: ASDF1234
        identifierType: ID
      - identifier: service-slug
        identifierType: SLUG

  # GitHub
  x-cortex-git:
    github:
      repository: &#x3C;org>/&#x3C;repo>
      basepath: &#x3C;SERVICE_NAME> # optional
   x-cortex-owners:
     - type: group
       name: &#x3C;ORGANIZATION>/&#x3C;TEAM> # Must be of form &#x3C;org>/&#x3C;team>
       provider: GITHUB
       description: # optional


  # GitLab
  x-cortex-git:
    gitlab:
      repository: &#x3C;namespace>/&#x3C;project>
      basepath: &#x3C;SERVICE_NAME> # optional
  x-cortex-owners:
    - type: group
      name: Team Name
      provider: GITLAB
      description: This is a description for this owner


  # Google
  x-cortex-owners:
    - type: group
      name: &#x3C;GROUP_NAME>
      provider: GOOGLE
  x-cortex-dependency:
    gcp:
      labels:
        - key: my-key-1
          value: my-value-1
        - key: my-key-2
          value: my-value-2
  x-cortex-infra:
    Google Cloud:
      resources:
        - resourceName: location/function
          projectId: project1
          resourceType: function
        - resourceName: example-bucket
          projectId: project1
          resourceType: storage
  x-cortex-slos:
    gcp:
      - projectId: cortex-gcp-integration
        serviceId: iLE2e4HvR_iVlxAaBbCc12
      - projectId: cortex-gcp-integration
        serviceId: adfdfdafd

  # Grafana
  x-cortex-dashboards:
    embeds:
      - type: grafana
        url: &#x3C;embed_url_to_dashboard>
         
  # incident.io
  x-cortex-incident-io:
    customFields:
    - name: Entity
      value: My Entity
      alias: my-default-alias
    - id: Entity_ID
      value: my-second-entity
      alias: my-other-alias

  # Jira
  x-cortex-issues:
    jira:
      labels:
        - &#x3C;LABEL1>
        - &#x3C;LABEL2>
      components:
        - &#x3C;COMPONENT1>
      projects:
        - project1
  # Optional: Override Cortex default Jira query
      defaultJql: 'status = "In Progress"'

  # Kubernetes
  x-cortex-k8s:
    deployment:
      - identifier: namespace/name
        cluster: dev # optional
      - identifier: experiment/scratch
        cluster: dev
      - identifier: default/cortex
        cluster: prod
    argorollout:
      - identifier: namespace/name
        cluster: dev
    statefulset:
      - identifier: namespace/name
        cluster: dev
    cronjob:
       - identifier: namespace/name
         cluster: dev

  # LaunchDarkly
  x-cortex-launch-darkly:
    projects:
      - key: project-key
        environments: # Optional
          - environmentName: prod
          - environmentName: staging
        alias: alias-1 # alias is optional and only relevant if you have opted into multi account support
      - tag: project-tag
        environments: # Optional
          - environmentName: prod
        alias: alias-2 # alias is optional and only relevant if you have opted into multi account support
    feature-flags:
      - tag: feature-flag-tag
        environments: # Optional
          - environmentName: staging
        alias: alias-3 # alias is optional and only relevant if you have opted into multi account support
  
  # Lightstep
  x-cortex-slos:
    lightstep:
      - streamId: &#x3C;STREAM_ID>
        targets:
        latency:
          - percentile: &#x3C;PERCENTILE>
            target: &#x3C;TARGET>
            slo: &#x3C;SLO>

  # Mend
  x-cortex-static-analysis:
    mend:
      applicationIds:
        - mend_id_1
        - mend_id_2
      projectIds:
        - project_id_1
        - project_id_2
  
  # Microsoft Teams
  x-cortex-microsoft-teams:
    channels:
    - name: team-engineering
      teamName: engineering
      description: This is a description for the engineering channel in Teams.
      notificationsEnabled: true
  
  # New Relic
  x-cortex-apm:
    newrelic:
      applications:
      - applicationId: &#x3C;APP_ID>
        alias: default-app
      tags:
      - tag: tagKey
        value: tagValue
        alias: default-app
  x-cortex-dashboards:
    embeds:
      - type: newrelic
        url: &#x3C;FULL_URL_TO_DASHBOARD>
  
  # While the `applications` wrapper format is the recommended format, Cortex also supports a flat array format:
  # x-cortex-apm:
  #   newrelic:
  #     - applicationId: &#x3C;APP_ID>

  # Okta
  x-cortex-owners:
    - type: group
      name: &#x3C;GROUP_NAME> # group name in Okta
      provider: OKTA
      description: # optional

  # OpsGenie
  x-cortex-oncall:
    opsgenie:
      type: SCHEDULE
      id: &#x3C;SCHEDULE_ID> # Optionally, can use the Rotation UUID instead
  x-cortex-owners:
    - type: group
      name: &#x3C;GROUP_NAME>
      provider: OPSGENIE
      description: # optional
  x-cortex-alerts:
    - type: opsgenie
      tag: &#x3C;KEY>
      value: &#x3C;VALUE>

  # PagerDuty
  x-cortex-oncall:
    pagerduty:
      id: &#x3C;SERVICE_ID> # Service ID
      type: SERVICE
  x-cortex-oncall:
    pagerduty:
      id: &#x3C;SCHEDULE_ID> # Schedule ID
      type: SCHEDULE
  x-cortex-oncall:
    pagerduty:
      id: &#x3C;POLICY_ID> # Escalation Policy ID
      type: ESCALATION_POLICY

  # Prometheus
  x-cortex-slos:
    prometheus:
      - errorQuery: &#x3C;query>
        totalQuery: &#x3C;query>
        slo: &#x3C;slo target number>
        alias: my-prometheus-instance
        name: my-slo-name

  # Rollbar
  x-cortex-rollbar:
    project: &#x3C;PROJECT_NAME> # projectName in Rollbar
     
  # Rootly
  x-cortex-rootly:
    services:
      - id: ASDF1234
      - slug: service-slug

  # Sentry
  x-cortex-sentry:
    projects:
      - name: my-project # projectName in Sentry
      - name: my-second-project
     
  # Semgrep
  x-cortex-semgrep:
    projects:
    - alias: my_org 
      projectId: 1234567
    - alias: other_org
      projectId: 7654321

  # ServiceNow
  x-cortex-servicenow:
    services:
    - tableName: cortex-services
      id: 1
  x-cortex-owners:
    - type: group
      name: My ServiceNow Team
      provider: SERVICE_NOW
      description: This is a description for this owner # optional

  # Slack
<strong>  x-cortex-slack:
</strong>    channels:
    - id: ABCDEF123
      notificationsEnabled: true
      description: This is a description for this Slack channel
    - name: team-engineering
      notificationsEnabled: true
      description: A description for this Slack channel.

  # Snyk
  x-cortex-snyk:
    projects:
      - organizationId:&#x3C;ORGANIZATION_ID>
        projectId: &#x3C;PROJECT_ID>
        source: CODE

  # SonarQube
  x-cortex-static-analysis:
    sonarqube:
      project: &#x3C;PROJECT_KEY> # projectKey in SonarQube
      alias: sonarqube-alias

  # Splunk Observability Cloud (SignalFX)
  x-cortex-slos:
    signalfx:
      - query: &#x3C;FULL_SFX_QUERY>  # Ex. sf_metric:"jvm.memory.max" AND area:"nonheap"
        rollup: &#x3C;ROLLUP>
        target: &#x3C;TARGET>
        lookback: &#x3C;LOOKBACK>
        operation: &#x3C;OPERATION>
  
  # Splunk On-Call (VictorOps)
  x-cortex-oncall:
    victorops:
      type: SCHEDULE
      id: &#x3C;SCHEDULE_ID>
       
  # Sumo Logic
  x-cortex-slos:
    sumologic:
      - id: 000000000001234
      - id: 000000000006789
      
  # Veracode
  x-cortex-static-analysis:
    veracode:
      applicationNames:
        - My Application
        - Second Application
      sandboxes:
        - applicationName: My Application
          sandboxName: My Sandbox
        - applicationName: Second Application
          sandboxName: Second Sandbox
          
  # Wiz
  x-cortex-wiz:
    projects:
      - projectId: 01234567-e65f-4b7b-a8b1-5b642894ec37
      
  # Workday
  x-cortex-owners:
    - type: group
      name: workday-team-tag
      provider: CORTEX
      description: This is a description for this owner.
      
  # xMatters
  x-cortex-oncall:
    xmatters:
      id: engineering_group
      type: SERVICE
</code></pre>


# YAML linter tool

The Cortex YAML linter validates your `cortex.yaml` files against both general YAML syntax and Cortex-specific schema requirements, catching invalid or incomplete entity definitions before they reach the platform.

This page covers the built-in tool available in the Cortex UI under **Tools > YAML Linter**. A separate linter is also built into the Cortex GitHub app, which runs checks on pull requests when you use GitHub in a [GitOps workflow](/configure/gitops).

## Using the YAML linter

### Validating a YAML file in the Cortex UI

1. From the main sidebar, expand **Tools**, then select **YAML linter**.<br>

   <div align="left" data-with-frame="true"><figure><img src="/files/8Csf7gbTKcJnPtAPQ0AW" alt="The YAML linter tool displayed in the Cortex UI." width="375"><figcaption></figcaption></figure></div>
2. Paste your YAML into the text editor, then click **Validate YAML**.
3. A status banner appears at the bottom of the page:
   * If the format is valid, a success message is displayed:

     <div align="left" data-with-frame="true"><figure><img src="/files/0UcjjVlYfTZF9KHBIXgA" alt="Valid YAML success icon and message."><figcaption></figcaption></figure></div>
   * If the format is incorrect:
     * For issues with the format of a Cortex-specific block, a warning banner appears:

       <div align="left" data-with-frame="true"><figure><img src="/files/PKCsd1r1G3ST1Ytagd2g" alt="The linter warning banner indicates that x-cortex-apm has an empty value in the YAML file."><figcaption></figcaption></figure></div>
     * For errors that cause the YAML to fail the linter check (such as missing a `title` or `x-cortex-tag`), a failure banner that includes the error message and which line is affected appears:

       <div align="left" data-with-frame="true"><figure><img src="/files/8RiohgjQ5tr9MB1uu8ht" alt="YAML fail icon and message."><figcaption></figcaption></figure></div>

### Validation scope

The linter checks for valid YAML structure and ensures required Cortex fields (like `openapi` version, `x-cortex-tag`, etc.) are present. If a required field is not present, this results in an error and the YAML does not pass the linter check.

The linter also validates the format of Cortex-specific blocks (e.g., `x-cortex-groups`, `x-cortex-firehydrant`) but does not verify the correctness of referenced data (such as whether a group or monitor ID actually exists). If there is an issue for a Cortex block, such as a block that doesn't contain a value, you will see a warning; however, the YAML will still pass the linter check.

If you submit a file with templating syntax (e.g., Jinja or cookiecutter variables like `{{ variable }}`), the linter will fail because these are not valid YAML until rendered. Only fully rendered YAML files will pass validation.

If the YAML is invalid or missing required fields, the linter will return errors indicating the line and nature of the problem.

### GitOps settings for the linter tool

If you are using GitHub in a GitOps workflow, you can adjust settings related to the linter. See [GitOps Settings](/configure/settings/gitops-settings) for more information.


# Adding entities

Entities are the foundational building blocks that represent the components of your software ecosystem—services, domains, teams, and more—giving your organization a shared way to describe what exists and how it connects. Defined in YAML and enriched with live data from your existing tools, entities come together to form a catalog that serves as a single source of truth.

Cortex provides a set of built-in entity types that cover the most common building blocks of a software organization. These defaults give you a strong foundation out of the box, so you can start cataloging your ecosystem without needing to design a schema from scratch.

Learn how to add built-in entity types and how to create your own custom entity types in the sections below:

* [Services](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services)
* [Domains](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/domains)
* [Teams](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams)
* [Custom entity types](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/entity-types)
* [Define dependencies](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/dependencies)

{% hint style="success" %}
Want to learn more? Check out the Cortex Academy course on [Catalogs, Entities, and Relationships](https://academy.cortex.io/courses/understanding-understanding-catalogs-entities-and-relationships).
{% endhint %}


# Adding services

Services are a default entity type in Cortex used to represent the codebase-like modules that make up your software ecosystem—microservices, libraries, components, etc. All entity types in Cortex, including services, are defined by a `cortex.yaml` file, which declares the entity's identity, ownership, dependencies, and links to the tools that support it (CI/CD, observability, on-call, documentation, and more). Once defined, a service becomes a first-class entity in your catalog, automatically enriched with live data pulled from your integrations.

Services are typically the most numerous entity type in a catalog and the closest match to how engineering teams already think about their work: as discrete units of code that do something specific, owned by someone, deployed somewhere, and depended on by other things. Modeling them consistently gives your organization a single place to answer questions that otherwise require digging through multiple tools—who owns this, what it depends on, whether it meets your standards, and where it runs. The result is a shared understanding that connects day-to-day engineering work to broader goals around quality, ownership, and operational maturity.

## Adding service entities to Cortex

Users with the `Edit Catalog` and `Edit Services` permissions can add service entities to Cortex.

Services can be added manually, imported, defined in YAML via GitOps, or created via the API.

### Importing services from an integration

1. From the main sidebar, expand **Catalogs**, then select **All entities**.
2. In the upper-right corner, click **Import entities**.
3. Select **Import discovered entities**.<br>

   <div align="left" data-with-frame="true"><figure><img src="/files/gsAeItQRO7Q5luKuFTR1" alt="The &#x27;Import discovered entities&#x27; tile is displayed." width="363"><figcaption></figcaption></figure></div>
4. Select the integration to import from.\
   The **Select entities to import** page is displayed.
5. A list of entities from the integration are displayed. Select the checkboxes next to the entities you want to import. If you have a large volume of entities, click the **Filter icon** in the upper-right corner of the results list to select and apply entity type filters.<br>

   <div align="left" data-with-frame="true"><figure><img src="/files/7JhDfxcU1sxtpRo0UUNf" alt="" width="330"><figcaption></figcaption></figure></div>
6. In the bottom-right corner, click **Next step**.\
   The **Edit details** page is displayed.
7. Configure the following options. The options shown are filtered at runtime based on the `entityType` (e.g. 'Members' is team-only, 'Dependencies' excludes domains/teams) and whether the required integrations are enabled (e.g. 'Communications' requires Slack, 'On-call' requires Opsgenie/PagerDuty, etc.).
   1. From the **Type** drop-down menu, select **Service.**
   2. In the **Details** sectio&#x6E;**:**
      1. Below **Entity name**, enter a name for the entity (required).
      2. The **Cortex tag** field is auto-populated based on the name of the entity (required). Its a unique identifier for the entity. This is also known as the `x-cortex-tag`.&#x20;
      3. Below **Description**, enter a description of the entity to help others understand its purpose.
      4. From the **Groups** drop-down men&#x75;**,** select a group or groups [to segment the entity](/ingesting-data-into-cortex/entities-overview/entities/groups).
   3. In the **Repository** section:
      1. From the **Provider** drop-down menu, select the repo provider.
      2. From the **Alias** drop-down menu, select the alias of the connected provider account that has access to the repository.
      3. From the **Repository** drop-down menu, select the repo associated with the entity. If you don't see it listed, click **Refresh repositories** to pull in the latest list.
      4. Below **Basepath**, enter the subdirectory within the repo where the entity's code lives. Leave blank if the entity occupies the entire repo.
   4. In the **Owners** section, define [ownership](/ingesting-data-into-cortex/entities-overview/entities/ownership) for the entity. Ownership can be assigned to either teams or individual users. It's recommended to select team owners to keep the ownership information up to date through any future personnel changes. To add a team or teams, click **Add** in the **Teams** area. To add an individual user or users, click **Add** in the **Users** area.
      * Cortex may recommend owners [based on repository activity](/ingesting-data-into-cortex/entities-overview/entities/ownership#recommendation). You can accept or reject the recommendations.
   5. In the **Links** section, click **Add** to add links to external documentation, such as runbooks, docs, logs, or custom categories.
   6. In the **Slack channels** section, click **Add** to link a Slack channel to the entity. If enabled, you'll receive notifications about the entity in the selected Slack channel.
   7. In the **Parents** section, select a parent domain or domains from the drop-down menu. This is where you configure the hierarchy for your entity, which can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
   8. In the **Dependencies** section, click **Add entity** to select an entity or entities that this entity depends on. These can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
8. If you selected more than one entity, click **Next entity** in the bottom-right corner of the page. <br>

   <div align="left" data-with-frame="true"><figure><img src="/files/wOtKl6Ln2jGVBCWTQiWh" alt="The &#x27;Next entity&#x27; link in the bottom-right corner of the page." width="375"><figcaption></figcaption></figure></div>
9. Click **Confirm import**.\
   The entity is imported into Cortex.&#x20;

### Manually adding services

1. From the main sidebar, expand **Catalogs**, then select **All entities**.
2. In the upper-right corner, click **Import entities**.
3. Select **Create entities manually**. \
   The **Edit details** page is displayed.
4. Configure the following options. The options shown are filtered at runtime based on the `entityType` (e.g. 'Members' is team-only, 'Dependencies' excludes domains/teams) and whether the required integrations are enabled (e.g. 'Communications' requires Slack, 'On-call' requires Opsgenie/PagerDuty, etc.).
   1. From the **Type** drop-down menu, select **Service.**
   2. **In the Details section:**
      1. Below **Entity name**, enter a name for the entity (required).
      2. The **Cortex tag** field is auto-populated based on the name of the entity (required). Its a unique identifier for the entity. This is also known as the `x-cortex-tag`.&#x20;
      3. Below **Description**, enter a description of the entity to help others understand its purpose.
      4. From the **Groups** drop-down men&#x75;**,** select a group or groups [to segment the entity](/ingesting-data-into-cortex/entities-overview/entities/groups).
   3. In the **Repository** section:
      1. From the **Provider** drop-down menu, select the repo provider.
      2. From the **Alias** drop-down menu, select the alias of the connected provider account that has access to the repository.
      3. From the **Repository** drop-down menu, select the repo associated with the entity. If you don't see it listed, click **Refresh repositories** to pull in the latest list.
      4. Below **Basepath**, enter the subdirectory within the repo where the entity's code lives. Leave blank if the entity occupies the entire repo.
   4. In the **Owners** section, define [ownership](/ingesting-data-into-cortex/entities-overview/entities/ownership) for the entity. Ownership can be assigned to either teams or individual users. It's recommended to select team owners to keep the ownership information up to date through any future personnel changes. To add a team or teams, click **Add** in the **Teams** area. To add an individual user or users, click **Add** in the **Users** area.
      * Cortex may recommend owners [based on repository activity](/ingesting-data-into-cortex/entities-overview/entities/ownership#recommendation). You can accept or reject the recommendations.
   5. In the **Links** section, click **Add** to add links to external documentation, such as runbooks, docs, logs, or custom categories.
   6. In the **Slack channels** section, click **Add** to link a Slack channel to the entity. If enabled, you'll receive notifications about the entity in the selected Slack channel.
   7. In the **Parents** section, select a parent domain or domains from the drop-down menu. This is where you configure the hierarchy for your entity, which can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
   8. In the **Dependencies** section, click **Add entity** to select an entity or entities that this entity depends on. These can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
5. Optionally, if you'd like to add another entity, click **Add entity** in the upper-right corner of the page.&#x20;
6. Click **Confirm import**.\
   The entity is imported into Cortex. If there are any errors, a banner appears at the bottom of the page with the errors that need to be fixed.

### Adding a service in YAML via GitOps

**Service entity descriptor**

A barebones spec file has the OpenAPI version, along with an `info` section that contains some basic details.

```yaml
openapi: 3.0.1
info:
  title: Account Service
  description: Brief summary of what this service does and who depends on it.
  x-cortex-tag: account-service
  x-cortex-type: service
```

**Required fields**

The following fields are required under `info`: `title`, `x-cortex-tag`, and `x-cortex-type`. The description is optional, but highly recommended as a best practice.

<details>

<summary>Expand to see the example YAML</summary>

```yaml
openapi: 3.0.1
info:
  title: Chat Service
  description: Chat service is responsible for handling the chat feature.
  x-cortex-tag: chat-service
  x-cortex-type: service
  x-cortex-parents: # parents can be of type domain only
  - tag: notifications-domain
  - tag: support-domain
  x-cortex-groups:
  - python
  x-cortex-owners:
  - type: group
    name: Delta
    provider: OKTA
    description: Delta Team
  x-cortex-slack:
    channels:
    - name: delta-team
      notificationsEnabled: true
      description: This is a description for the delta-team Slack channel # optional
  x-cortex-link:
  - name: Chat ServiceAPI Spec
    type: OPENAPI
    url: ./docs/chat-service-openapi-spec.yaml
  x-cortex-custom-metadata:
    core-service: true
  x-cortex-dependency:
    - tag: authentication-service
    - tag: chat-database
  x-cortex-git:
    github:
      repository: org/chat-service
  x-cortex-oncall:
    pagerduty:
      id: ASDF1234
      type: SCHEDULE
  x-cortex-apm:
    datadog:
      monitors:
        - 12345
  x-cortex-issues:
    jira:
      projects:
        - CS
```

</details>

### Adding a service via the Cortex API

You can create, update, and delete services using the Cortex API. See [Catalog entities](/api/readme/catalog-entities) for more information.

## Viewing services

The **Services** page lists every service entity that's been imported into Cortex. To open it, expand **Catalogs** in the main sidebar and select **Services**. The page opens to the **Mine** tab if you own any services, and defaults to the **All** tab otherwise. Each row shows the service's name and tag.&#x20;

<div data-with-frame="true"><figure><img src="/files/arqg91oXKhvYVd7TU0Jd" alt="Overview of the Services page in the Cortex UI."><figcaption></figcaption></figure></div>

### Searching across and filtering services

<div align="left" data-with-frame="true"><figure><img src="/files/AwOZoKbvLmnX3u6CKR39" alt="The search and filter options in the upper-right corner of the page."><figcaption></figcaption></figure></div>

There are several ways to search and filter your services list.

1. From the main sidebar, expand **Catalogs**, then select **Services.**
2. Do one of the following:
   * Select the **All** tab to search and filter across all of your organization's services.
   * Select the **Mine** tab to search and filter only the services you own.
3. Do any or all of the following:
   * To find specific services, use the search bar in the upper-right corner of the services list and type to search.
   * Click **Name** to select whether you want to sort by name or identifier, and whether to sort by ascending or descending order.
   * Click **Display** to choose whether to show archived services in the list, and select which columns to display alongside services.
   * Click into a row to learn more about:
     * **Incidents** - Displays how many active incidents are associated with a given service. This information is pulled from FireHydrant, incident.io, PagerDuty, and Rootly.
     * **Health** - When you click into this column in an service's row, you can view more information about:
       * **Monitors** - Shows how services are performing against monitors you’ve created in your APM. When a service is passing all monitors, this cell will display `All OK`; otherwise, it displays `Failing`, `Warning`, or `No Data`, along with how many monitors the service is not hitting. This information is pulled from Datadog.
       * **Error rate** - Shows the percentage of transactions that result in a failure during a pre-specified window. This information is pulled from New Relic.
       * **Apdex (Application Performance Index)** - Ratio of the number of satisfied and tolerating requests to the total number requests made. This information is pulled from New Relic.<br>

         <div align="left" data-with-frame="true"><figure><img src="/files/9uAkJtwfj7iG0vPclWjs" alt="Shows the health and incidents columns on the entities page." width="304"><figcaption></figcaption></figure></div>
     * Columns that rely on an integration display **Not connected** when the integration hasn't been set up. If the integration is connected but the entity has no associated data or configuration, the cell displays **None** instead.
   * Click **Filter** to narrow down your list by by domain, entity type, group, owner, or team.

## Editing a service entity

Users with the `Edit Catalog` and `Edit Services` permissions can edit service entities.

Service entities can be modified at any time. Follow the steps below to edit a service entity.

1. Navigate to the entity's page.
2. In the upper-right corner, click **Configure entity**.\
   The entity details page opens.
3. In the upper-right corner, select either **UI editor** or **YAML editor**.
4. Make your changes. Note that the Cortex tag is uneditable.
5. Click **Save changes**.\
   The service entity is updated.

{% hint style="info" %}
It's possible to change the entity type via the Cortex YAML. See [Changing an entity's type](/ingesting-data-into-cortex/entities-overview/entities#changing-an-entitys-type) for more information.
{% endhint %}


# Adding domains

Domains are a default entity type in Cortex used to group entities into hierarchical units. You can group by product area, functionality, systems, business units, or something unique to your organization. With this feature, you can cluster entities into a single, hierarchical domain that can include both parents and children.

You can define a list of other entities as children for a domain, allowing you to represent a hierarchy of how your entities are modeled across your workspace. This hierarchy is available to view in the Domains catalog, on a domain entity's details page, and in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph). The domain hierarchy can also be used to configure ownership inheritance, helping you keep track of ownership in case of personnel changes at your organization.

## Adding domain entities to Cortex

Users with the `Edit Catalog` and `Edit Domains` permissions can add domain entities to Cortex.

Domains can be added manually, imported, defined in YAML via GitOps, or created via the API.

For simplicity, it's recommended to add the highest-level domain first, then select it as the parent for subsequent domains. However, you can add parents and children to any domain at any point.

### Importing domains from an integration

1. From the main sidebar, expand **Catalogs**, then select **All entities**.
2. In the upper-right corner, click **Import entities**.
3. Select **Import discovered entities**.<br>

   <div align="left" data-with-frame="true"><figure><img src="/files/gsAeItQRO7Q5luKuFTR1" alt="The &#x27;Import discovered entities&#x27; tile is displayed." width="363"><figcaption></figcaption></figure></div>
4. Select the integration to import from.\
   The **Select entities to import** page is displayed.
5. A list of entities from the integration are displayed. Select the checkboxes next to the entities you want to import. If you have a large volume of entities, click the **Filter icon** in the upper-right corner of the results list to select and apply entity type filters.<br>

   <div align="left" data-with-frame="true"><figure><img src="/files/7JhDfxcU1sxtpRo0UUNf" alt="" width="330"><figcaption></figcaption></figure></div>
6. In the bottom-right corner, click **Next step**.\
   The **Edit details** page is displayed.
7. Configure the following options. The options shown are filtered at runtime based on the `entityType` (e.g. 'Members' is team-only, 'Dependencies' excludes domains/teams) and whether the required integrations are enabled (e.g. 'Communications' requires Slack, 'On-call' requires Opsgenie/PagerDuty, etc.).
   1. From the **Type** drop-down menu, select **Domain.**
   2. In the **Details** sectio&#x6E;**:**
      1. Below **Entity name**, enter a name for the entity (required).
      2. The **Cortex tag** field is auto-populated based on the name of the entity (required). Its a unique identifier for the entity. This is also known as the `x-cortex-tag`.&#x20;
      3. Below **Description**, enter a description of the entity to help others understand its purpose.
      4. From the **Groups** drop-down men&#x75;**,** select a group or groups [to segment the entity](/ingesting-data-into-cortex/entities-overview/entities/groups).
   3. In the **Repository** section:
      1. From the **Provider** drop-down menu, select the repo provider.
      2. From the **Alias** drop-down menu, select the alias of the connected provider account that has access to the repository.
      3. From the **Repository** drop-down menu, select the repo associated with the entity. If you don't see it listed, click **Refresh repositories** to pull in the latest list.
      4. Below **Basepath**, enter the subdirectory within the repo where the entity's code lives. Leave blank if the entity occupies the entire repo.
   4. In the **Owners** section, define [ownership](/ingesting-data-into-cortex/entities-overview/entities/ownership) for the entity. Ownership can be assigned to either teams or individual users. It's recommended to select team owners to keep the ownership information up to date through any future personnel changes. To add a team or teams, click **Add** in the **Teams** area. To add an individual user or users, click **Add** in the **Users** area.
      * Cortex may recommend owners [based on repository activity](/ingesting-data-into-cortex/entities-overview/entities/ownership#recommendation). You can accept or reject the recommendations.
      * When adding an owner, you can also configure one of the following inheritance options:
        * **Append** - Select this option to add your entity as an additional owner to all of its child entities.
        * **Fallback** - Select this option to add your entity as an owner to child entities if the child entity has no other valid owners.
        * **None** - Select this option if you do not want to configure inheritance. The owner owns the domain you are creating, but will not be configured as an appended or a fallback owner.
   5. In the **Links** section, click **Add** to add links to external documentation, such as runbooks, docs, logs, or custom categories.
   6. In the **Slack channels** section, click **Add** to link a Slack channel to the entity. If enabled, you'll receive notifications about the entity in the selected Slack channel.
   7. In the **Parents** section, select a parent domain or domains from the drop-down menu. This is where you configure the hierarchy for your entity, which can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
   8. In the **Children** section, select children entities. This is where you configure the hierarchy for your entity, which can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
8. If you selected more than one entity, click **Next entity** in the bottom-right corner of the page. <br>

   <div align="left" data-with-frame="true"><figure><img src="/files/wOtKl6Ln2jGVBCWTQiWh" alt="The &#x27;Next entity&#x27; link in the bottom-right corner of the page." width="375"><figcaption></figcaption></figure></div>
9. Click **Confirm import**.\
   The entity is imported into Cortex.&#x20;

### Manually adding domains

1. From the main sidebar, expand **Catalogs**, then select **All entities**.
2. In the upper-right corner, click **Import entities**.
3. Select **Create entities manually**. \
   The **Edit details** page is displayed.
4. Configure the following options. The options shown are filtered at runtime based on the `entityType` (e.g. 'Members' is team-only, 'Dependencies' excludes domains/teams) and whether the required integrations are enabled (e.g. 'Communications' requires Slack, 'On-call' requires Opsgenie/PagerDuty, etc.).
   1. From the **Type** drop-down menu, select **Domain.**
   2. **In the Details section:**
      1. Below **Entity name**, enter a name for the entity (required).
      2. The **Cortex tag** field is auto-populated based on the name of the entity (required). Its a unique identifier for the entity. This is also known as the `x-cortex-tag`.&#x20;
      3. Below **Description**, enter a description of the entity to help others understand its purpose.
      4. From the **Groups** drop-down men&#x75;**,** select a group or groups [to segment the entity](/ingesting-data-into-cortex/entities-overview/entities/groups).
   3. In the **Repository** section:
      1. From the **Provider** drop-down menu, select the repo provider.
      2. From the **Alias** drop-down menu, select the alias of the connected provider account that has access to the repository.
      3. From the **Repository** drop-down menu, select the repo associated with the entity. If you don't see it listed, click **Refresh repositories** to pull in the latest list.
      4. Below **Basepath**, enter the subdirectory within the repo where the entity's code lives. Leave blank if the entity occupies the entire repo.
   4. In the **Owners** section, define [ownership](/ingesting-data-into-cortex/entities-overview/entities/ownership) for the entity. Ownership can be assigned to either teams or individual users. It's recommended to select team owners to keep the ownership information up to date through any future personnel changes. To add a team or teams, click **Add** in the **Teams** area. To add an individual user or users, click **Add** in the **Users** area.
      * Cortex may recommend owners [based on repository activity](/ingesting-data-into-cortex/entities-overview/entities/ownership#recommendation). You can accept or reject the recommendations.
      * When adding an owner, you can also configure one of the following inheritance options:
        * **Append** - Select this option to add your entity as an additional owner to all of its child entities.
        * **Fallback** - Select this option to add your entity as an owner to child entities if the child entity has no other valid owners.
        * **None** - Select this option if you do not want to configure inheritance. The owner owns the domain you are creating, but will not be configured as an appended or a fallback owner.
   5. In the **Links** section, click **Add** to add links to external documentation, such as runbooks, docs, logs, or custom categories.
   6. In the **Slack channels** section, click **Add** to link a Slack channel to the entity. If enabled, you'll receive notifications about the entity in the selected Slack channel.
   7. In the **Parents** section, select a parent domain or domains from the drop-down menu. This is where you configure the hierarchy for your entity, which can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
   8. In the **Children** section, select children entities. This is where you configure the hierarchy for your entity, which can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
5. Optionally, if you'd like to add another entity, click **Add entity** in the upper-right corner of the page.&#x20;
6. Click **Confirm import**.\
   The entity is imported into Cortex. If there are any errors, a banner appears at the bottom of the page with the errors that need to be fixed.

### Adding a domain in YAML via GitOps

The hierarchy of entities in Cortex is based on that hierarchy being defined in the entity's YAML file; Cortex does not set hierarchies based on a YAML file's location in your repository.

**Domain entity descriptor**

If your entity is a domain, you must specify `x-cortex-type` as `domain`:

```yaml
openapi: 3.0.1
info:
  title: Payments
  description: This is a description of the domain.
  x-cortex-tag: payments-domain
  x-cortex-type: domain
```

**Domain hierarchies**

Hierarchies can be defined in two directions:

* **Top-down** (from the parent) - Use the `x-cortex-children` tag in the parent entity YAML to list its children.
* **Bottom-up** (from the child) - Use the `x-cortex-parents` tag in the child entity YAML to list its parents.

Both approaches produce the same hierarchy; choose whichever fits your workflow. For example, if you frequently update a group of child domains together, defining them on the parent YAML is often more efficient.

**Domain parents**

Define another entity as the parent for a domain, allowing you to represent a hierarchy of how your entities are modeled across your workspace using the `x-cortex-parents` tag:

```yaml
openapi: 3.0.1
info:
  title: Payments
  description: This is a description of the domain.
  x-cortex-tag: payments-domain
  x-cortex-parents:
  - tag: parent-domain-1
  - tag: parent-domain-2
```

{% hint style="info" %}
Parent entities must be of type `domain`.
{% endhint %}

**Domain children**

Define a list of other entities as children for a domain, allowing you to represent a hierarchy of how your entities are modeled across your workspace using the `x-cortex-children` tag:

```yaml
openapi: 3.0.1
info:
  title: Payments
  description: This is a description of the domain.
  x-cortex-tag: payments-domain
  x-cortex-type: domain
  x-cortex-children:
  - tag: child-domain-1
  - tag: child-service-1
  - tag: child-resource-1
```

**Ownership inheritance**

A common use case for domains is defining ownership for the subtree of entities. Instead of defining ownership individually for every entity in your catalog, you can define ownership at the domain level and have that pass down to all of its children:

```yaml
openapi: 3.0.1
info:
  title: Payments
  description: This is a description of the domain.
  x-cortex-tag: payments-domain
  x-cortex-type: domain
  x-cortex-owners:
      - type: GROUP
        name: cortexapps/engineering
        provider: GITHUB
        inheritance: APPEND
```

The `inheritance` type for each owner can be one of `APPEND`, `FALLBACK`, or `NONE`. If not set, inheritance is defaulted to `NONE`.

* `APPEND` - This owner is appended to the list of owners for all child entities.
* `FALLBACK` - In the case where a child has no valid owners, including fallbacks, this fallback will be assigned as the owner. Note that this only applies to a child entity down the hierarchy; it is not the fallback for the parent domain itself.
* `NONE` - This owner owns the domain, but not necessarily any of its children (no inheritance).

**Example cortex.yaml file**

{% hint style="info" %}
The YAML definition for a domain entity can take file names other than `cortex.yaml` or `cortex.yml`; see the [GitOps example repository structure](/configure/gitops#how-gitops-works-in-cortex).
{% endhint %}

<details>

<summary>Expand to see the example YAML</summary>

```yaml
openapi: 3.0.1
info:
  title: Chat
  description: Chat domain.
  x-cortex-tag: chat-domain
  x-cortex-type: domain
  x-cortex-children: # children can be of type service, resource, or domain
    - tag: chat-service
    - tag: chat-database
  x-cortex-parents: # parents can be of type domain only
    - tag: payments-domain
    - tag: web-domain
  x-cortex-owners:
    - type: group
      name: Support
      provider: OKTA
      description: Support Team
  x-cortex-slack:
    channels:
    - name: support-team
      notificationsEnabled: true
      description: This is a description for the support-team Slack channel # optional
  x-cortex-oncall:
    pagerduty:
      id: ASDF2345
      type: SCHEDULE
  x-cortex-apm:
    datadog:
      monitors:
        - 23456
```

</details>

### Adding a domain via the Cortex API

You can create, update, and delete domains using the Cortex API. See [Catalog entities](/api/readme/catalog-entities) for more information.

## Viewing domains

The **Domains** page lists every service entity that's been imported into Cortex. To open it, expand **Catalogs** in the main sidebar and select **Domains**. The page opens to the **Mine** tab if you own any domains, and defaults to the **All** tab otherwise. Each row shows the domain's name and tag.&#x20;

<div data-with-frame="true"><figure><img src="/files/L2vBSwOOkGQp7YjtNxwH" alt="Overview of the Domains page in the Cortex UI."><figcaption></figcaption></figure></div>

### Searching across and filtering domains

<div data-with-frame="true"><figure><img src="/files/ibQWIR5rvufnK7TNAlil" alt="The search and filter options in the upper-right corner of the page."><figcaption></figcaption></figure></div>

There are several ways to search and filter your domains list.

1. From the main sidebar, expand **Catalogs**, then select **Domains.**
2. Do one of the following:
   * Select the **All** tab to search and filter across all of your organization's domains.
   * Select the **Mine** tab to search and filter only the domains you own.
3. Do any or all of the following:
   * To find specific domains, use the search bar in the upper-right corner of the domains list and type to search.
   * Click **Name** to select whether you want to sort by name or identifier, and whether to sort by ascending or descending order.
   * Click **Display** to choose whether to show archived domains in the list, and select which columns to display alongside domains. See [Viewing the domain hierarchy](#displaying-domains-in-hierarchy) below.
   * Click **Filter** to narrow down your list by domain, entity type, group, owner, or team.

### Viewing the domain hierarchy

Follow the steps below to display domains in hierarchy.

1. From the main sidebar, expand **Catalogs**, then select **Domains.**
2. Click **Display** at the top of the domains list.
3. Toggle on **Display hierarchy**.<br>

   <div align="left" data-with-frame="true"><figure><img src="/files/3ztjPIuyscUmWsHG5V1A" alt="The &#x27;Display hierarchy&#x27; toggle enabled." width="272"><figcaption></figcaption></figure></div>
4. Click **Done**.

{% hint style="info" %}
You can also view the hierarchy for a given domain on its [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details).&#x20;
{% endhint %}

### Viewing the Relationships page

If the domain has parents or children, those appear on the Relationships page.

<div align="left" data-with-frame="true"><figure><img src="/files/uV86Cy1Auoskg5vsjV0g" alt="Relationships page for the Authentication domain, showing its parent (Identity) above it and two children (OAuth2 identity service and SSO integration) below it in a vertical hierarchy diagram." width="563"><figcaption></figcaption></figure></div>

To access the Relationships page of an entity:

1. From the main sidebar, expand **Catalogs**, then select **Domains.**
2. Click **Display** at the top of the domains list.
3. Select the entity whose relationship graph you want to view.
4. In the entity sidebar, select **Relationships**.<br>

   <div align="left" data-with-frame="true"><figure><img src="/files/VvhmEgsdhDGaGGdUXpSj" alt="Relationships page for the Authentication domain, showing its parent (Identity) above it and two children (OAuth2 identity service and SSO integration) below it in a vertical hierarchy diagram." width="375"><figcaption></figcaption></figure></div>
5. Do any of the following:
   1. Click the **Archive icon** to show or hide archived relationships.
   2. Click the **Filter icon** to narrow the scope of the graph.
   3. By default, the domain hierarchy is displayed as a graph. Click the **Table mode** icon to switch to a tabular view.
   4. Click **Configure** in the upper-right corner to configure the relationship type and its associated entities. &#x20;

See [Relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph) for more information.

## Editing a domain entity

Users with the `Edit Catalog` and `Edit Domains` permissions can edit domain entities.

Domain entities can be modified at any time. Follow the steps below to edit a domain entity.

1. Navigate to the entity's page.
2. In the upper-right corner, click **Configure entity**.\
   The entity details page opens.
3. In the upper-right corner, select either **UI editor** or **YAML editor**.
4. Make your changes. Note that the Cortex tag is uneditable.
5. Click **Save changes**.\
   The domain entity is updated.

{% hint style="info" %}
It's possible to change the entity type via the Cortex YAML. See [Changing an entity's type](/ingesting-data-into-cortex/entities-overview/entities#changing-an-entitys-type) for more information.
{% endhint %}


# Add teams

**Teams** serve as both an entity representing your organization in Cortex and as [owners](/ingesting-data-into-cortex/entities-overview/entities/ownership) for different entities in the catalogs. Teams offers a centralized place for the most important information about each group, making it easier for everyone to find what they need.

Teams can be assessed via [Scorecards](/standardize/scorecards), interact with integrations, and leverage [custom data](/ingesting-data-into-cortex/entities-overview/entities/custom-data). They can also be configured in a hierarchy.

## View teams

To view your teams, navigate to **Catalogs > Teams**.

![Click Teams in the main nav to view your list of teams.](/files/SiEargkfxZRj38OFPNuu)

When you open the [Teams catalog page](https://app.getcortexapp.com/admin/catalogs/teams), you'll see **Mine** and **All**, which denote teams you belong to and all teams at your organization, respectively. The teams that appear under "All" will automatically display as a [hierarchy](#understanding-hierarchies), whereas those under "Mine" will be listed individually.

### View the teams leaderboard

On the right side of the Teams catalog page, see the Scorecard Leaderboard, which highlights the ten best-performing teams within your organization.

The leaderboard is calculated from the average of [Scorecard](/standardize/scorecards) scores for all entities owned by a team. Change in rank is based on the team's score 7 days ago. You can use the dropdown to select a different Scorecard, allowing you to view the leaderboard based on specific Scorecards.

{% hint style="success" %}
The leaderboard gamifies entity quality and encourages team members to achieve goals. This creates a culture of accountability, where everyone has visibility into how they're performing.
{% endhint %}

### View an individual team's page

Each team has its own details page, where you can view key details about the team. Click a team from the Teams catalog page to view its details.

At the top of a team details page, you’ll find on-call information, Slack channels, and parent and children teams.

Additional information appears in tabs on the team's details page:

<figure><img src="/files/mr5qyA6eZsywgyvRjV8s" alt=""><figcaption><p>A team's details page includes an overview, team members, owned entities, and dependencies.</p></figcaption></figure>

* The **Overview** tab includes:
  * Vulnerabilities and issues from linked integrations.
  * How the team is performing across Scorecards. By default, this will show the level that the team’s entities have reached in each Scorecard.
    * On the right, enable the toggle next to **Aggregate children scores** to include child entities in the Scorecard overview.
  * A list of recent events associated with this team, such as alerts from [PagerDuty](/ingesting-data-into-cortex/integrations/pagerduty).
* The **Dependencies** tab shows any incoming or outgoing dependencies associated with this team.
* The **Team members** tab includes a list of all team members and their roles. When available, Cortex will also pull in profile photos from your Git provider.
* The **Entities** tab shows a list of all entities that the team owns.

Learn more about the sidebar links in the [Entity details page](/ingesting-data-into-cortex/entities-overview/entities/details) documentation.

### Ownership

Teams not only allow you to collect vital information in a single place, but are also crucial for ownership. Rather than assign an entity to individual team members, you can assign ownership to an entire team. This makes it easy to assign multiple team members to an entity, and it ensures that when a team’s composition changes, ownership is updated accordingly.

Read more in the [Ownership documentation](/ingesting-data-into-cortex/entities-overview/entities/ownership).

## Creating a team

You can create teams:

* By importing them from a connected integration (e.g., Workday, GitHub)
* Manually in the Cortex UI
* Via the entity descriptor YAML through [GitOps](/configure/gitops)
* Via the [API](/api/readme/teams)

### Understanding hierarchies

You can configure teams to reflect the actual hierarchy at your organization while creating or importing teams in Cortex. A team can be defined as the parent of one or more teams while also being the child of another team.

When you access the [Teams catalog](https://app.getcortexapp.com/admin/catalogs/teams), individual teams and parent teams are displayed by default. Parent teams have an arrow next to their name, indicating that you can expand to view children teams.

![Parent teams display with an arrow icon to expand the hierarchy.](/files/Sq9XBozAHUjNkrVb2TsF)

In the above example, `My Company` is a parent team with 7 child teams nested under it.

### Create a team

See the tabs below for instructions on each method.

{% tabs %}
{% tab title="Import" %}
**Importing a team from an integration**

If you have an existing source of truth for your teams and team members, we recommend importing teams. By integrating with your identity provider at this stage, Cortex will automatically sync team pages with your source of truth so you don't have to update information in more than one place when people join or leave teams.

Each integration syncs teams daily.

{% hint style="warning" %}
You can only import entities from integrations that have already been configured.
{% endhint %}

**Supported integrations**

Teams from the following integrations can be imported:

* [Azure DevOps](/ingesting-data-into-cortex/integrations/azuredevops)
* [BambooHR](/ingesting-data-into-cortex/integrations/bamboohr)
* [Entra ID (formerly Azure Active Directory)](/ingesting-data-into-cortex/integrations/entraid)
* [GitHub](/ingesting-data-into-cortex/integrations/github)
* [GitLab](/ingesting-data-into-cortex/integrations/gitlab)
* [Google](/ingesting-data-into-cortex/integrations/google)
* [Okta](/ingesting-data-into-cortex/integrations/okta)
* [Opsgenie](/ingesting-data-into-cortex/integrations/opsgenie)
* [ServiceNow](/ingesting-data-into-cortex/integrations/servicenow)
  * Before following the import process, you must [configure table mappings](/ingesting-data-into-cortex/integrations/servicenow#step-2-configure-table-mappings).
* [Workday](/ingesting-data-into-cortex/integrations/workday)
  * For the Workday integration, you can enable [automatic import of discovered teams](#auto-import-teams).

**Importing teams**

After configuring an integration that includes teams, follow these steps to import teams:

1. In Cortex, navigate to **Catalogs > All entities**, then click **Import entities**.
2. Choose **Import discovered entities**.\
   ![](/files/gsAeItQRO7Q5luKuFTR1)
3. Select the integration to import from.
4. On the following page, after the integration sync is complete, a list of entities from the integration are displayed. Check the boxes next to any entities you want to import.\
   ![](/files/7JhDfxcU1sxtpRo0UUNf)
   * If you have a large volume of entites, click **Filter** in the upper right corner of the results list to select and apply entity type filters.
5. At the bottom of the page, click **Next step**.
6. Edit the details for the entity:
   * **Type**: Select `Team`.
   * **Name**: Enter a human readable name for your team.
   * **Identifier**: This field is auto-populated based on your entity name. It is a unique identifier for your entity. This is also known as the `x-cortex-tag`.
   * **Description**: Enter a description of the team to help others understand its purpose.
   * **Groups**: Select [groups to segment](/ingesting-data-into-cortex/entities-overview/entities/groups) your entity.
   * **Members**: Select members of your team. Team members will be marked as owners of entities and receive notifications about entities owned by the team if notifications are enabled.
   * **Links**: Add links to external documentation, such as runbooks, docs, logs, or custom categories.
   * **Slack channels**: Link the team's associated Slack channel. If [notifications are configured](/configure/settings/notifications), the team will receive notifications here.
     * You must have the [Slack integration](/ingesting-data-into-cortex/integrations/slack) configured before linking a channel.
   * **Parents** and **Children**: Define parent and children teams. This is where you configure the hierarchy for your entity. These can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
   * **On-call**: Configure the on-call service associated with this team. When selected, you will see the latest on-call information displayed on the team's details page.
7. If you selected more than one entity: After the first entity is configured, click the name of the next entity on the right to navigate to the detail editor for that entity.\
   ![](/files/qnlTVcgrq0sKxk2Z4FTM)
8. Click **Confirm import**.
   {% endtab %}

{% tab title="Manual" %}
**Manually creating teams**

If you don’t have an identity provider with updated team information, you can create a team manually within Cortex. Because teams are important for effective ownership, it's recommended that you create teams in Cortex even if you don't have a single source of truth for team information.

1. In Cortex, navigate to **Catalogs > Teams**, then click **Import teams**.
2. Choose **Create entities manually**.\
   ![](/files/gsAeItQRO7Q5luKuFTR1)
3. Configure the form:
4. Configure the team details:
   * **Type**: Select `Team`.
   * **Name**: Enter a human readable name for your team.
   * **Identifier**: This field is auto-populated based on your entity name. It is a unique identifier for your entity. This is also known as the `x-cortex-tag`.
   * **Description**: Enter a description of the team to help others understand its purpose.
   * **Groups**: Select [groups to segment](/ingesting-data-into-cortex/entities-overview/entities/groups) your entity.
   * **Members**: Select members of your team. Team members will be marked as owners of entities and receive notifications about entities owned by the team if notifications are enabled.
   * **Links**: Add links to external documentation, such as runbooks, docs, logs, or custom categories.
   * **Slack channels**: Link the team's associated Slack channel. If [notifications are configured](/configure/settings/notifications), the team will receive notifications here.
     * You must have the [Slack integration](/ingesting-data-into-cortex/integrations/slack) configured before linking a channel.
   * **Parents** and **Children**: Define parent and children teams. This is where you configure the hierarchy for your entity. These can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
   * **On-call**: Configure the on-call service associated with this team. When selected, you will see the latest on-call information displayed on the team's details page.
5. Click **Confirm import**.

Once you've created a team, you can view it on the **Teams** page within the hierarchy. If you haven't added parents or children, you can disable **View as hierarchy** to see the list of all teams.
{% endtab %}

{% tab title="Entity descriptor" %}
**Adding Cortex-managed teams**

You can manually create teams in Cortex and define them in the entity descriptor.

You can also define teams as owners via entity descriptors. See the [Ownership documentation](/ingesting-data-into-cortex/entities-overview/entities/ownership) for more information.

**Team entity descriptor**

If your entity is a team, you must specify `x-cortex-type` as `team`.

```yaml
openapi: 3.0.1
info:
  title: Payments Team
  description: This is my cool team.
  x-cortex-tag: payments-team
  x-cortex-type: team
```

The `x-cortex-team` tag has two main sections: `groups` and `members`.

**Adding groups to the team entity descriptor**

Use `groups` to link your team entity with a team on a different platform that you have integrated with Cortex. You can only link one group to a team entity.

For example, you can specify:

```
openapi: 3.0.1
info:
  title: Example Team
  description: My Cool Team
  x-cortex-type: team
  x-cortex-tag: example-team
  x-cortex-team:
      groups:
      - name: okta-security-team
        provider: OKTA
```

Under `groups`, when you specify `okta-security-team`, your team will contain all the members from your `okta-security-team`.

Now, if you specify the `okta-security-team` in your [`x-cortex-owners`](#ownership) on any of your other entities, they will automatically recognize `example-team` as a team that owns their entity.

**Adding team members to the team entity descriptor**

`members` can be used to add individual members to your team when you have a use case for a team entity that doesn't correspond exactly to a team on one of your integrations. Members support `roles`. For example, the following entity includes a member who has the `product-manager` role and a member who has both the `engineering-manager` role and `manager` role:

```
openapi: 3.0.1
info:
  title: Example Team
  description: My Cool Team
  x-cortex-type: team
  x-cortex-tag: example-team
  x-cortex-team:
      members:
      - name: Product Manager
        email: product-manager@cortex.io
        notificationsEnabled: true
        roles: 
          - tag: product-manager
      - name: Engineering Manager
        email: engineering-manager@cortex.io
        notificationsEnabled: true
        roles: 
          - tag: engineering-manager
          - tag: manager 
```

After specifying the YAML example above, your team now will contain `Product Manager` and `Engineering Manager`. If `product-manager@cortex.io` or `engineering-manager@cortex.io` were to correspond with the email of an actual account in Cortex, they would start seeing `example-team` being displayed as a team that they're a part of (i.e., it would start showing up in their `Mine` tab in catalogs that contain teams).

[Roles](#adding-team-member-roles) must be defined for your workspace in your [Entity Settings page](https://app.getcortexapp.com/admin/settings/entities), under the "Teams" tab.

{% hint style="info" %}
The `role` field in member is optional. In order to be considered valid, a team must have a non-empty group.
{% endhint %}

**Team children**

You can define a list of other teams as children, allowing you to represent a hierarchy of how your teams are modeled across your workspace, using the `x-cortex-children` tag.

```yaml
openapi: 3.0.1
info:
  title: Payments
  description: This is my cool team.
  x-cortex-tag: payments-team
  x-cortex-type: team
  x-cortex-children:
  - tag: child-team-1
  - tag: child-team-2
```

This hierarchy is available to look at in the Teams catalog page.

The hierarchy of entities in Cortex is based on that hierarchy being defined in the entity's YAML file; Cortex does not set hierarchies based on a YAML file's location in your repository.

**Team parents**

Team children allow you to define the team relationship from the top-down, but in some cases it may be easier to define the team hierarchy from the bottom-up. For these cases, `x-cortex-parents` can be added to any entity's YAML to define its parents.

```yaml
openapi: 3.0.1
info:
  title: Payments
  description: This is my cool team.
  x-cortex-tag: payments-team
  x-cortex-type: team
  x-cortex-parents:
  - tag: parent-team-1
  - tag: parent-team-2
```

**Example cortex.yaml**

Note: the YAML definition for a team entity can take file names other than `cortex.yaml` or `cortex.yml`; see the [GitOps example repository structure](/configure/gitops#how-gitops-works-in-cortex).

```yaml
openapi: 3.0.1
info:
  title: Chat Team
  description: Chat team.
  x-cortex-tag: chat-team
  x-cortex-type: team
  x-cortex-team:
      groups:
      - name: okta-chat-team
        provider: OKTA
      members:
      - name: Product Manager
        email: product-manager@cortex.io
        notificationsEnabled: true
      - name: Engineering Manager
        email: engineering-manager@cortex.io
        notificationsEnabled: true
  x-cortex-children: # children can be of type team
    - tag: chat-infra-team
    - tag: chat-sre-team
  x-cortex-slack:
    channels:
    - name: chat-team
      notificationsEnabled: true
      description: This is a description for the chat-team Slack channel # optional
  x-cortex-oncall:
    pagerduty:
      id: ASDF2345
      type: SCHEDULE
```

{% endtab %}

{% tab title="API" %}
**Creating teams via the API**

You can create, update, and delete teams using the [Cortex API](/api/readme/teams).
{% endtab %}
{% endtabs %}

### Edit teams

It is possible to edit entities after creating them:

1. Navigate to the entity's page.
2. In the upper right corner, click **Configure entity**.
3. Make any desired changes.
   * Note: The only field you cannot edit is the identifier.
4. At the bottom of the screen, click **Save changes**.

## Adding team member roles

You can manually create a team member role:

1. In Cortex, navigate to [**Settings > Entities > Teams**](https://app.getcortexapp.com/admin/settings/entities/teams?activeTab=TeamMemberRoles).
2. Click **Add role**.
3. In the "Add role" modal, configure the role:
   * **Role name**: Enter the role's name.
   * **Tag**: The tag - a unique identifier for the role - automatically populates based on the role name.
   * **Role description**: Enter a description of the role.
   * **Enable notifications by default**: If notifications are enabled, members with this role will receive relevant updates on Scorecards, Initiatives, and more.
4. Click **Save**.

#### Apply role to team members

You can apply a role only to manually-created team members. Team members who were imported from an identity integration will retain the role that was imported.

To apply a role:

1. In Cortex, navigate to **Catalogs > Teams**.
2. Click into a team.
3. In the upper right corner, click **Configure entity**.
4. Click **Members**.
5. Next to a team member, click the edit icon.
6. In the side panel, add a new team role.
7. Click **Update**.

## Adjusting team settings

Under [**Settings > Entities > Teams**](https://app.getcortexapp.com/admin/settings/entities/teams), there are several settings relating to teams. You can select which identity providers to use to sync teams and team memberships, configure automatic import from Workday, configure entity editing access, and sync or create roles. Learn more in [Entity settings](/configure/settings/entity-settings).


# Add custom entity types

Every entity you add to your workspace is associated with an entity type. Cortex comes with several built-in entity types, but you can [create unlimited custom entity types](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/entity-types) to extend your catalogs.

There are two distinct parts of this process: [Creating the entity type itself](#create-custom-entity-types) (via the UI or API), then [creating entities of that custom type](#create-custom-entities) (via the UI, GitOps, or API).

{% hint style="success" %}
Want to learn more? Check out the Cortex Academy course on [Catalogs, Entities, and Relationships](https://academy.cortex.io/courses/understanding-understanding-catalogs-entities-and-relationships), available to all Cortex customers and POVs.
{% endhint %}

## View entity types

To view all entity types, go to **Catalogs > All Entities** then click the [**Entity types** tab](https://app.getcortexapp.com/admin/entities?activeTab=EntityTypes).

A Cortex logo appears next to built-in entity types. When you hover over the logo, you will see a "Powered by Cortex" banner:

<div align="left"><figure><img src="/files/B6MeZaglbUSl9Rde7d96" alt=""><figcaption></figcaption></figure></div>

The other entity types in the list are custom types.

## Create custom entity types

You can create custom entity types:

* Manually in the Cortex UI
* Via the [API](/api/readme/entity-types)

When creating an entity type, keep in mind that these will ultimately dictate how you import specific entities later on. After creating the type itself, you will be able to [create entities of that type](#creating-custom-entities) (via the UI, API, or GitOps).

To create, edit, and delete entity types, your user or API key must have the `Edit entity types` permission.

{% tabs %}
{% tab title="Cortex UI" %}
**Create entity types in the Cortex UI**

1. In Cortex, navigate to **Catalogs > All entities**.
2. Click the **Entity types** tab, then click **Create entity type**.\\

   <figure><img src="/files/pR6qsGUnqg36b6XsOPZF" alt="In the upper right, click &#x22;Create entity type.&#x22;"><figcaption></figcaption></figure>
3. Configure the form:
   * **Name**: Enter a human-readable name that will appear in the catalog for this entity type.
   * **Type**: Enter a unique identifier that corresponds to the entity type. This will be used to specify the type defined in the YAML definitions for imported entities.
   * **Description**: Optionally, enter a description for the entity type.
   * **Display icon**: Select an icon to appear alongside the entity type throughout the app.
   * **Schema**: Define a [JSON schema](#json-schema-for-custom-entity-types) that will be used to validate the `x-cortex-validation` block of a given entity’s YAML.
     * This can be used to enforce certain attributes about entities, such as a region or version number. Attributes defined in the schema will be required when creating an entity of that type, which can then be validated in Scorecards. Learn more under [JSON schema for custom entity types](#json-schema-for-custom-entity-types).
     * In the example screen shot below, we’ve created a custom entity type called `Employee` — this is what we’ll use to represent individuals at our organization. In the schema section, you can see that each profile is required to include an employee’s location. This means every time you create an entity of type "Employee," you will define the employee's location.\\

       <div align="left"><figure><img src="/files/s9RSMK6Aspbr2A8g4cXp" alt="A custom entity called Employee contains example JSON demonstrating how to configure a required &#x22;location&#x22; field." width="351"><figcaption></figcaption></figure></div>
4. At the bottom of the page, click **Create**.

After saving, the entity type will appear in the **Entity types** tab under **Catalogs > All entities**, and you are now able to import entities of that type.

If you want entities of the new entity type to automatically belong to a specific catalog, you can configure the catalog's defined entity types while [creating a new catalog](#create-catalogs) or you can [edit an existing catalog](#edit-catalogs) to update the entity types.
{% endtab %}

{% tab title="API" %}
**Create entity types via the API**

You can create, update, and delete entity types using the [Cortex API](/api/readme/catalog-entities).

Learn more about the [JSON schema](#json-schema-for-custom-entity-types) below.
{% endtab %}
{% endtabs %}

### JSON schema for custom entity types

Entity type definitions require a JSON schema that outlines the attributes that entities should conform to.

Custom entity type definitions are powered by the open-source [JSON Schema](https://json-schema.org/) project.

The JSON schema for a custom entity type ensures consistency and validation when creating entities of that type. The attributes listed under `required` in the schema must be defined for entities of that type according to the outlined `properties`.

In the example below, `location` is required when creating this type of entity, but the schema also includes `department` as a possible property.

```json
{
  "type": "object",
  "required": [
    "location"
  ],
  "properties": {
    "location": {
      "type": "string"
    },
    "department": {
      "type": "string"
    }
  }
}
```

| Field        | Definition                                                                                                       | Required                                     |
| ------------ | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
| `type`       | Type of entity and/or required component: `array`, `boolean`, `integer`, `null`, `number`, `object`, or `string` | Yes                                          |
| `required`   | Required specs for the entity type                                                                               |                                              |
| `properties` | Properties of the required specs (including `type`)                                                              | Yes only if the `required` field is not null |

#### Adding an entity schema for new custom entities

When creating a new entity of the custom type, if the entity type's JSON schema requires certain attributes, you must include the metadata for those attributes on that entity.

<details>

<summary>Add attributes via JSON schema</summary>

While [creating a custom entity in the Cortex UI](#cortex-ui-1), you can enter JSON for the entity's schema into the Schema field.

Based on the [example above](#json-schema-for-custom-entity-types), the entity schema format would look like the following:

```json
{
    "location": "San Diego",
    "department": "Engineering"
}
```

</details>

<details>

<summary>Add attributes via YAML</summary>

If you are following a GitOps workflow, or if you are editing the entity's YAML directly in the Cortex UI, you can update the custom entity's metadata in the YAML.

Based on the [example above](#json-schema-for-custom-entity-types), the entity YAML would look like the following:

```
x-cortex-type: org-employees
x-cortex-definition:
   location: San Diego
   department: Engineering
```

When creating a custom entity, the `x-cortex-type` (the custom entity type) and the `x-cortex-definition` are required. Learn more under [Create custom entities in the entity descriptor](#entity-descriptor).

</details>

#### Metadata in the entity details page

Defining a JSON schema enables visibility on an [entity's detail page](/ingesting-data-into-cortex/entities-overview/entities/details). The schema and the defined properties will appear under the **Metadata** section on the entity's overview, making it easy for you to identify key specs.

In the example below, the entity "Sally S" displays metadata for the property "location."

<div align="left"><figure><img src="/files/2KTliDCdKGh7jR2sNeSn" alt="An entity called &#x22;Sally S&#x22; displays metadata. For a property called &#x22;location,&#x22; the value is &#x22;San Diego.&#x22;"><figcaption></figcaption></figure></div>

## Create custom entities

After [creating your custom entity type](#create-custom-entity-types), you can create entities of that custom type:

* in the Cortex UI
* in the [entity descriptor YAML](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file) via [GitOps](/configure/gitops)
* via the [Cortex API](/api/readme/catalog-entities)

To create custom entities, your user or API key must have the `Edit entities` permission.

{% tabs %}
{% tab title="Cortex UI" %}
**Create custom entities in the Cortex UI**

Before creating a custom entity in the UI, make sure you have UI-based editing enabled for this entity type in [**Settings > GitOps**](https://app.getcortexapp.com/admin/settings/gitops).

1. In the main nav of Cortex, click **Catalogs > All entities**.
2. At the top of the Services page, click **+Import entities**.
3. Choose **Create entities manually**.\
   ![](/files/gsAeItQRO7Q5luKuFTR1)
4. Configure the form:
   * **Type**: Select your custom entity type.
   * **Entity schema**: Enter a JSON schema to define your custom entity.
     * For example, if the entity type's schema requires location and department, your new entity's schema might look like this:\\

       <figure><img src="/files/IwEbFOTmGnsmflzz3iuy" alt="The entity schema includes &#x22;location&#x22; and &#x22;department&#x22; metadata"><figcaption></figcaption></figure>
     * Click **Show example** above the schema to view an example of how the entity's schema should be formatted. To use the example as a starting point, click **Copy example** then paste it into the **Entity schema** text editor.
     * See [JSON schema for custom entity types](#json-schema-for-custom-entity-types) for more information.
   * **Entity name**: Enter a human readable name for your entity.
   * **Identifier**: This field is auto-populated based on your entity name. It is a unique identifier for your entity. This is also known as the `x-cortex-tag`.
   * **Description**: Enter a description of the entity to help others understand its purpose.
   * **Groups**: Select [groups to segment](/ingesting-data-into-cortex/entities-overview/entities/groups) your entity.
   * **Owners**: Define [ownership](/ingesting-data-into-cortex/entities-overview/entities/ownership) for your entity. We recommend selecting team owners to keep your ownership information up-to-date through any future personnel changes.
   * **Links**: Add links to external documentation, such as runbooks, docs, logs, or custom categories.
   * **Parents**: Define parent domains. This is where you configure the hierarchy for your entity. These can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
   * **Dependencies**: Select entities that this entity depends on. These can be visualized in the [relationship graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).
   * **On-call**: Configure on-call information.
   * **Repository**: Select the repository associated with this entity.
5. When you are finished, click **Confirm import** at the bottom of the page.
   {% endtab %}

{% tab title="Entity descriptor" %}
**Create custom entities in the entity descriptor**

Before creating a custom entity via GitOps, make sure you have UI-based editing disabled for this this entity type in [**Settings > GitOps**](https://app.getcortexapp.com/admin/settings/gitops).

If your entity is of a custom type, you must specify `x-cortex-type` and `x-cortex-definition`.

The `x-cortex-definition` field is validated against the [entity type definition](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/entity-types) that you created via the UI or API. If your custom entity type does not have specific requirements, entities of that type still need a non-null definition specified, like `x-cortex-definition: {}`.

**Example cortex.yaml**

```yaml
openapi: 3.0.1
info:
  title: Sally S
  description: Technical writer
  x-cortex-tag: employee-sally
  x-cortex-type: org-employees
  x-cortex-definition:
    location: San Diego
    department: Engineering
```

{% endtab %}

{% tab title="API" %}
You can create, read, update, and delete entities via the [Cortex API](/api/readme/catalog-entities).

To delete entities, your API key must have the `Delete entities` permission.
{% endtab %}
{% endtabs %}

## Managing custom entities

### Edit custom entities

It is possible to edit entities after creating them:

1. Navigate to the entity's page.
2. In the upper right corner, click **Configure entity**.
3. Make any desired changes.
   * Note: The only field you cannot edit is the identifier.
4. At the bottom of the screen, click **Save changes**.

### Add custom entities to catalogs

After an entity is imported or created, it will automatically belong to a catalog based on the entity type criteria set for each catalog. When you [create a custom catalog](#create-catalogs), you can set the entity type criteria.

By default, any [custom entity types](#create-entity-types) you create will belong to the Infrastructure catalog. If you do not want the entity type to belong to this catalog, you can add the entity type to a different catalog's definition.

## Managing custom entity types

After creating a custom entity type, you can view or edit its schema, view a list of entities of that type, and validate the schema of entities of that type.

### View custom entity types

You can view a custom entity type's schema and a list of entities of that type.

1. Navigate to **Catalogs > All entities**, then click the [Entity types tab](https://app.getcortexapp.com/admin/entities?activeTab=types).
2. Click into an entity type.
   * The schema is displayed on the entity type page.

     <div align="left"><figure><img src="/files/4MYP83qDfMMtZFMrM3yB" alt="The schema is displayed on the entity type page." width="563"><figcaption></figcaption></figure></div>
   * Click the **Entities** tab to view a list of entities of that type.

     <figure><img src="/files/0jp7poZWs5zxMLYbK8GW" alt="Click the Entities tab to view a list of entities of the custom type."><figcaption></figcaption></figure>

     * Learn more about the health and incident data columns in [Key performance indicators listed for all entities](/ingesting-data-into-cortex/entities-overview/entities#key-performance-indicators-listed-for-all-entities).\\

### Edit custom entity types

1. Navigate to **Catalogs > All entities**, then click the [Entity types tab](https://app.getcortexapp.com/admin/entities?activeTab=types).
2. Click into an entity type.
3. In the upper right corner, click **Edit**.
4. Make changes to your entity type, then at the bottom of the page, click **Save**.
   * You cannot edit the entity type's unique identifier.

### Validate an entity schema for a custom entity type

1. Navigate to **Catalogs > All entities**, then click the [Entity types tab](https://app.getcortexapp.com/admin/entities?activeTab=types).
2. Click into an entity type.
3. Click the **Schema linter** tab.

   <div align="left"><figure><img src="/files/byZmyxlGyBHuFiVK4ZXU" alt="Click the Schema linter tab, then enter your JSON schema into the text box."><figcaption></figcaption></figure></div>
4. In the text editor, paste in your entity's JSON schema to verify that it is properly formatted for this entity type.
   * On the right side of the page, click **Show example** to see an example of how the schema should be formatted.
   * If you want to use the example as a starting point, click **Copy example**, then paste it into the text editor.

     <figure><img src="/files/AW1yG9ZPMSgMRak0Su7Q" alt="Click Show example to see an example schema, then click Copy example."><figcaption></figcaption></figure>
5. In the upper right side of the text editor, click **Validate Schema**.

## Using custom entity types or custom data

In some instances, you may want to use custom data instead of a custom entity type. This is recommended if you need more flexibility for these entity types; they may not always require specific metadata.

While a custom entity type's metadata will appear on the overview of an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details), custom data does not appear there. Instead, it appears in the **Custom data** sidebar of an entity details page.

It is possible to create an entity type with an empty properties schema:

```json
{
  "type": "object",
    "required": []
    "properties": {}
}
```

This entity type will display in the catalogs, but entities of this type won't be validated against certain specs. Such properties can instead be defined using [custom data](/ingesting-data-into-cortex/entities-overview/entities/custom-data).

A schema is ideal for enforcing static properties across all entities, while custom data allows users to augment and update attributes.


# Defining dependencies

In Cortex, you have the ability to define outgoing dependencies on other entities. Cortex can also automatically [discover dependencies](#discovery) for some integrations. Having dependencies defined powers the ability to [notify owners](#automated-dependency-notifications) when a dependency deprecates its API or makes backwards incompatible changes, and the ability to visualize dependencies in a [relationship graph](#visualize-dependencies-in-the-relationship-graph).

Incoming dependencies are inferred based on the outgoing dependency definitions.

### Visualize dependencies in the relationship graph

In Cortex, you can visualize dependencies using the relationship graph at **Tools > Relationship graphs**. See the [Relationship graph documentation](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph) for more information.

### Automated dependency notifications

{% hint style="info" %}
This feature is available in beta. Please reach out to your Cortex Customer Success Manager for access.
{% endhint %}

When a dependency deprecates its API or makes backwards incompatible changes, Cortex surfaces these issues via these methods:

* Breaking API changes are listed in your Cortex workspace under [**Settings > Breaking API changes**](https://app.getcortexapp.com/admin/settings/breaking-api-changes).
* Cortex attempts to automatically make comments on PRs containing breaking OpenAPI changes that have downstream dependencies that Cortex knows about.
* If a breaking change is merged to the default branch, Cortex alerts dependency owners via Slack that a breaking change was merged.

## Discovery

Cortex can automatically discover dependencies from your integrations:

* [AWS](/ingesting-data-into-cortex/integrations/aws)
* [Azure Resources](/ingesting-data-into-cortex/integrations/azureresources)
* [Datadog](/ingesting-data-into-cortex/integrations/datadog)
* [Dynatrace](/ingesting-data-into-cortex/integrations/dynatrace)
* [Google Cloud](/ingesting-data-into-cortex/integrations/google)
* [New Relic](/ingesting-data-into-cortex/integrations/newrelic)

## How to define dependencies

You can define dependencies manually via an entity's YAML descriptor, via the Cortex UI (if UI editing is enabled), or via the API.

Your user or API key need the `Edit entities` permission.

{% tabs %}
{% tab title="Cortex UI" %}
**Define dependencies in the Cortex UI**

1. Navigate to the entity where you need to define a dependency.
2. In the upper right corner of the entity details page, click **Configure entity**.
3. Click the **Hierarchy** tab.
4. In the **Dependencies** block, click **+Add entity**.\
   ![Add dependencies to an entity](/files/Od9EEZiDs9hIBY71CvkG)
5. In the dropdown menu, choose an entity.
6. Optionally, select an endpoint.
   * In order for an endpoint to populate in this dropdown, it must first be defined as a path in the entity's YAML file. See ["Set an endpoint for a dependency"](#set-an-endpoint-for-a-dependency) below.
7. Click **Add**.

**Set an endpoint for a dependency**

Before you can select an endpoint from the dropdown when manually defining a dependency, that endpoint must be defined as a path in the entity's YAML file. See the example below:

```yaml
openapi: 3.0.1
info:
  title: Endpoint Example Service
  description: "This is an example"
  x-cortex-tag: endpoint-example-service
  x-cortex-type: service
paths:
  /hello/world:
    get:
      description: Some description
      requestBody:
        description: optional
      responses:
        "200":
          description: optional
      deprecated: false
  /another/path:
    put:
      deprecated: false
```

In the UI, the paths will appear in the **Endpoint** dropdown:\
![The paths appear in the Endpoint dropdown](/files/RoK5KdlTOFS9411CsLrm)
{% endtab %}

{% tab title="Entity descriptor" %}
**Define dependencies in the entity descriptor**

The `x-cortex-dependency` field allows you to define a list of outgoing dependencies. A dependency should be directed towards an outgoing service or resource, or more granularly, to a specific endpoint of that entity.

```yaml
info:
  x-cortex-dependency:
    - tag: braavos
      method: GET
      path: /2.0/users/
      description: ensure user has payment information configured
      metadata:
        tags:
          - billing
          - identity
        prod: true
```

| Field           | Description                                                                         | Optional?                       |
| --------------- | ----------------------------------------------------------------------------------- | ------------------------------- |
| **tag**         | The `tag` of the entity this entity depends on, i.e. the callee. See `x-cortex-tag` | No                              |
| **method**      | HTTP method *if* depending on a specific endpoint                                   | Required if `path` is present   |
| **path**        | The actual endpoint this dependency refers to                                       | Required if `method` is present |
| **description** | A description of the dependency.                                                    | Yes                             |
| **metadata**    | JSON metadata tags for the relationship. Supports arbitrary objects.                | Yes                             |
| {% endtab %}    |                                                                                     |                                 |

{% tab title="API" %}
**Define dependencies via the API**

See the [API docs](/api/readme/dependencies) for authentication details.

{% hint style="warning" %}
YAML is the source of truth. If a dependency has already been set through the `cortex.yaml`, the API will return an error.
{% endhint %}

Endpoints are optional. A dependency optionally references an endpoint (`method` and `path`) of the callee, and this must already be defined in the callee's `cortex.yaml` within the `paths` field. If no endpoint is referenced it is assumed that the caller depends on **all** endpoints of the callee.

For all requests `method` or `path` are optional, however if one is present the other must also be present.

When interacting with an existing dependency, the `method` and `path` must be specified correctly to identify it.

<table><thead><tr><th>Field</th><th width="351">Description</th><th>Optional?</th></tr></thead><tbody><tr><td><strong>callerTag</strong></td><td>The <code>tag</code> of the caller.</td><td>No</td></tr><tr><td><strong>calleeTag</strong></td><td>The <code>tag</code> the caller depends on.</td><td>No</td></tr><tr><td><strong>method</strong></td><td>HTTP method <em>if</em> depending on a specific endpoint</td><td>Required if <code>path</code> is present</td></tr><tr><td><strong>path</strong></td><td>The actual endpoint (as defined in the OpenAPI file) the caller depends on</td><td>Required if <code>method</code> is present</td></tr><tr><td><strong>description</strong></td><td>A description of the dependency.</td><td>Yes</td></tr><tr><td><strong>metadata</strong></td><td>JSON metadata tags for the relationship. Supports arbitrary objects.</td><td>Yes</td></tr></tbody></table>

```json
{
  "callerTag": "my-service",
  "calleeTag": "braavos",
  "path": "/2.0/users/",
  "method": "GET",
  "description": "ensure user has payment information configured",
  "metadata": {
    "tags": ["billing", "identity"],
    "prod": true
  }
}
```

**Create a dependency**

`POST /api/v1/catalog//dependencies/?method=&path=`

```json
{
  "description": "ensure user has payment information configured",
  "metadata": 
}
```

**Retrieve a dependency**

`GET /api/v1/catalog//dependencies/?method=&path=`

**Update a dependency**

`PUT /api/v1/catalog//dependencies/?method=&path=`

{% hint style="warning" %}
PUT replaces entire object. The request body is considered a modified version of the already existing entity. Leaving a field out of the JSON will be interpreted as `null`.
{% endhint %}

```json
{
  "description": "ensure user has payment information configured",
  "metadata": 
}
```

**Delete a dependency**

`DELETE /api/v1/catalog//dependencies/?method=&path=`

**Bulk create or update dependencies**

`PUT /api/v1/catalog/dependencies`

:::caution PUT replaces entire object The request body is considered a modified version of the already existing entity. Leaving a field out of the JSON will be interpreted as `null`. :::

```json
{
  "values": {
    "my-service": [
      {
        "tag": "braavos",
        "path": "/2.0/users/",
        "method": "GET",
        "description": "ensure user has payment information configured",
        "metadata": 
      }
    ],
    "my-other-service": [
      {
        "tag": "my-service",
        "path": "/1.0/widget/",
        "method": "GET",
        "description": "get widget",
        "metadata": 
      }
    ]
  }
}
```

{% endtab %}
{% endtabs %}

## Sync dependencies

Cortex syncs AWS dependencies every day at 8:00 a.m. UTC. All other dependencies sync at 12:00 a.m. UTC.

You must have the `Enable entity dependency discovery` permission to manually sync dependencies.

If you need to sync dependencies manually:

1. Navigate to **Tools > Relationship graphs**.
2. In the upper right corner of the page, click the menu icon, then click **Sync dependencies**.\
   ![](/files/oRNSrQmLhBxgzXa8Mpii)

## Troubleshooting and FAQ

#### What if I have multiple dependency sources?

When leveraging multiple dependency sources (such as Datadog and a catalog entity's YAML), all the sources will be merged together and deduplicated.

For example, if an entity YAML indicates `X->Y` and Datadog indicates `X->Y` and `X->Z`, we will have two edges presented (`X->Y` and `X->Z`).


# Entity details page

Each entity has a dedicated details page that centralizes all related data, helping developers stay focused by reducing context switching. To open an entity's details page, click its name either while browsing a catalog or from the **Catalogs > All entities** page. From here you can quickly access key information:

* **Active incidents** - Any ongoing incidents are surfaced at the top of the page for immediate visibility.
* **Sidebar** - [Customize which metadata](#configuring-the-entity-metadata-sidebar) appears here by pinning the information most relevant to you. Supported data includes on-call schedules, owners, Slack or Microsoft Teams channels, groups, repositories, entity relationships, doc links, project management, custom data, and code quality.

{% hint style="success" %}
During an incident, the entity details page surfaces everything you need in one place: the active incident, owners and on-call contacts, the relevant Slack channel, affected dependencies, and recent deploys.
{% endhint %}

{% hint style="info" %}
Fields only appear in the overview if data is available. For example, the **Slack channels** field won't display unless you have the Slack integration configured.
{% endhint %}

## Locating an entity's unique identifiers

The [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) and the [Cortex ID](/ingesting-data-into-cortex/entities-overview/entities#cortex-id) are displayed below the entity's name.

<div align="left" data-with-frame="true"><img src="/files/Bk3B3XWmSABGIfdLTKeW" alt="The entity&#x27;s unique identifiers appear below its name." width="400"></div>

## Configuring the entity's sidebars

Each entity details page includes two sidebars—the entity details sidebar on the left and the entity metadata sidebar on the right—each serving a distinct purpose.

### Configuring the entity details sidebar

The entity details sidebar appear on the left side of every entity page. It provides a deeper view into the entity's recent deploys, events, security vulnerabilities, monitoring metrics, and more, giving you the context needed to resolve incidents quickly.

The entity details sidebar contains the following information about the entity:

#### Overview categories

* **Relationships** - See how an entity connects to the rest of your catalog including domain hierarchy, team hierarchy, dependencies, and any custom relationship types you've defined. See [Defining relationship types](/ingesting-data-into-cortex/entities-overview/entities/defining-relationship-types) and [Viewing relationships on an entity page](/ingesting-data-into-cortex/entities-overview/entities/defining-relationship-types#view-relationships-on-entity-pages).
* **API explorer** - Pulls from [API documentation](/ingesting-data-into-cortex/entities-overview/entities/external-docs) added to your entity.
* **Events** - A list of recent events sourced from [deploys](/ingesting-data-into-cortex/entities-overview/entities/deploys), [AWS ECS](/ingesting-data-into-cortex/integrations/aws), [Azure DevOps](/ingesting-data-into-cortex/integrations/azuredevops), [GitHub](/ingesting-data-into-cortex/integrations/github), [GitLab](/ingesting-data-into-cortex/integrations/gitlab), [Kubernetes](/ingesting-data-into-cortex/integrations/kubernetes), [Opsgenie](/ingesting-data-into-cortex/integrations/opsgenie), [PagerDuty](/ingesting-data-into-cortex/integrations/pagerduty), [Sentry](/ingesting-data-into-cortex/integrations/sentry), and [Snyk](/ingesting-data-into-cortex/integrations/snyk).
* **Links & docs** - [Documentation links](/ingesting-data-into-cortex/entities-overview/entities/external-docs) you have added to the entity, along with documentation pulled from the related repository.
* **Owners** - See the teams who own the entity, the related Slack or Microsoft Teams channels, and a list of team members. Learn more about [defining entity owners](/ingesting-data-into-cortex/entities-overview/entities/ownership).
* **Entity YAML** - View the [entity YAML](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file) that defines the selected entity.

  <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>If you have <a href="/pages/KBttn6YUdEgixQGROHKf#step-1-disable-ui-editing">GitOps editing</a> enabled for this entity, and you have the <code>View GitOps logs</code> permission, this page displays the source of the YAML file and a preview of the latest GitOps log.</p></div>

#### Cortex features

* **Scorecards** - A list of any [Scorecards](/standardize/scorecards) that are in progress where this entity is being scored. Additionally, see the average score, median score, and a graph showing the entity's scores over time.
  * Above the *Scorecard* section, you can choose which scores to include in calculations if the entity is in a hierarchy:
    * **Domains** - Click **This entity only** to view only the scores that apply to the domain you are viewing. Select **Include entity's children** to include both the parent domain and its child entities in the score calculations.
    * **Entities with a custom relationship type** - Click **This entity only** to view only the scores that apply to the entity you are viewing. Click **\[Relationship type] only** to include both the parent and its child entities in the score calculations.
    * **Teams** - Click **This entity only** to view the scores that apply only to the team you are viewing. Click **Include entity's children** to include scores for the team, the team's children, entities owned by the team, and entities owned by the team's children.
* **Initiatives** - A list of all active [Initiatives](/improve/initiatives) for this entity, including the Scorecard's current level and the due date of the Initiative.
* **Workflows** - A list of [Workflows](/streamline/workflows) that include this entity.

  <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>If you are a designated approver for any pending Workflows, they will appear at the top of this page. You can also view recently run Workflows and trigger any related Workflows from here.</p></div>

#### Connections

The *Connections* section displays integration data grouped by context. Once you configure integrations, data appears in the following sections on the entity page:

* **CI/CD** - Pulls from [deploys API](/ingesting-data-into-cortex/entities-overview/entities/deploys), [Azure DevOps](/ingesting-data-into-cortex/integrations/azuredevops), [Bitbucket](/ingesting-data-into-cortex/integrations/bitbucket), [Buildkite](/ingesting-data-into-cortex/integrations/buildkite), [CircleCI](/ingesting-data-into-cortex/integrations/circleci), [GitHub](/ingesting-data-into-cortex/integrations/github), and [GitLab](/ingesting-data-into-cortex/integrations/gitlab).
* **Cloud** - Pulls from [AWS](/ingesting-data-into-cortex/integrations/aws) and [Kubernetes](/ingesting-data-into-cortex/integrations/kubernetes).
* **Code quality** - Pulls from [Codecov](/ingesting-data-into-cortex/integrations/codecov) and [SonarQube](/ingesting-data-into-cortex/integrations/sonarqube).
* **Custom data & metrics** - Pulls from [custom data](/ingesting-data-into-cortex/entities-overview/entities/custom-data) and [Eng Intelligence custom metrics](/improve/eng-intelligence/custom-metrics).
* **Dashboard** - Pulls from [charts](/ingesting-data-into-cortex/entities-overview/entities/external-docs#embed-dashboards) configured in the entity's YAML file for [Datadog](/ingesting-data-into-cortex/integrations/datadog), [Grafana](/ingesting-data-into-cortex/integrations/grafana), and [New Relic](/ingesting-data-into-cortex/integrations/newrelic).
* **Error tracking** - Pulls from [BugSnag](/ingesting-data-into-cortex/integrations/bugsnag), [Rollbar](/ingesting-data-into-cortex/integrations/rollbar), and [Sentry](/ingesting-data-into-cortex/integrations/sentry).
* **Feature flags** - Pulls from [LaunchDarkly](/ingesting-data-into-cortex/integrations/launchdarkly).
* **Observability** - Pulls from [Coralogix](/ingesting-data-into-cortex/integrations/coralogix), [Datadog](/ingesting-data-into-cortex/integrations/datadog), [Dynatrace](/ingesting-data-into-cortex/integrations/dynatrace), [Google Observability Cloud](/ingesting-data-into-cortex/integrations/google), [Lightstep](/ingesting-data-into-cortex/integrations/lightstep), [New Relic](/ingesting-data-into-cortex/integrations/newrelic), [Prometheus](/ingesting-data-into-cortex/integrations/prometheus), [Splunk Observability Cloud](/ingesting-data-into-cortex/integrations/splunk-observability) (formerly SignalFX), and [Sumo Logic](/ingesting-data-into-cortex/integrations/sumologic).
* **On-call & incidents** - On-call information from [Opsgenie](/ingesting-data-into-cortex/integrations/opsgenie), [PagerDuty](/ingesting-data-into-cortex/integrations/pagerduty), [Splunk On-Call](/ingesting-data-into-cortex/integrations/splunk-oncall) (formerly VictorOps), and [xMatters](/ingesting-data-into-cortex/integrations/xmatters), and incidents pulled from [incident.io](/ingesting-data-into-cortex/integrations/incidentio), [PagerDuty](/ingesting-data-into-cortex/integrations/pagerduty), [FireHydrant](/ingesting-data-into-cortex/integrations/firehydrant), and [Rootly](/ingesting-data-into-cortex/integrations/rootly).
* **Packages** - Pulls from the [packages API](/api/readme/packages) and any packages automatically discovered from your configured git repositories.
* **Project management** - Pulls from [Azure DevOps](/ingesting-data-into-cortex/integrations/azuredevops), [ClickUp](/ingesting-data-into-cortex/integrations/clickup), [GitHub](/ingesting-data-into-cortex/integrations/github), [GitLab](/ingesting-data-into-cortex/integrations/gitlab), and [Jira](/ingesting-data-into-cortex/integrations/jira).
* **Security** - Pulls from [Apiiro](/ingesting-data-into-cortex/integrations/apiiro), [Checkmarx](/ingesting-data-into-cortex/integrations/checkmarx), [Codecov](/ingesting-data-into-cortex/integrations/codecov), [GitHub](/ingesting-data-into-cortex/integrations/github), [GitLab](/ingesting-data-into-cortex/integrations/gitlab), [Mend](/ingesting-data-into-cortex/integrations/mend), [Semgrep](/ingesting-data-into-cortex/integrations/semgrep), [Snyk](/ingesting-data-into-cortex/integrations/snyk), [SonarQube](/ingesting-data-into-cortex/integrations/sonarqube), [Veracode](/ingesting-data-into-cortex/integrations/veracode), and [Wiz](/ingesting-data-into-cortex/integrations/wiz).
* **Version control** - Pulls from [Azure DevOps](/ingesting-data-into-cortex/integrations/azuredevops), [Bitbucket](/ingesting-data-into-cortex/integrations/bitbucket), [GitHub](/ingesting-data-into-cortex/integrations/github), and [GitLab](/ingesting-data-into-cortex/integrations/gitlab).

#### Plugins

The *Plugins* section displays [plugins](/streamline/plugins) that are relevant to this entity.

### Configuring the entity metadata sidebar

The entity metadata sidebar appears on the right side of every entity page. You can control which metadata categories are displayed, reorder them, and apply the same layout across multiple entity types at once.

#### Expanding or collapsing the metadata sidebar

Click the **arrow icon** in the bottom-right corner to expand or collapse the metadata sidebar.

<div align="left" data-with-frame="true"><img src="/files/B0vSTwUs66DgX7xEI43O" alt="The arrow icon in the bottom-right corner of the page." width="400"></div>

#### Customizing the metadata sidebar

Users who are admins or who have the `Edit Entity Types` permission can customize the metadata sidebar.

1. In the bottom-right corner of the metadata sidebar, click the **Configure entity sidebar** icon.

   <div align="left" data-with-frame="true"><img src="/files/2okzb7JdlzJ4bGEjf5Bn" alt="The Configure Entity icon icon in the bottom-right corner of the page." width="400"></div>
2. To reorder a category, hover over the **grip icon** and drag it to the desired position. To hide a category, click the **eye icon** next to it. Repeat as necessary.

   <div align="left" data-with-frame="true"><img src="/files/eRMiOZrZZ06XBwzVjYEP" alt="The Grip icon next to an entity." width="250"></div>
3. From the *Apply layout to entity types* drop-down menu, select which entity types to apply this configuration to.

   <div align="left" data-with-frame="true"><img src="/files/E68PrA7T1R5M28VagrR4" alt="The Apply layout to entity types drop-down 
   menu in the bottom-right corner of the page." width="250"></div>
4. Click **Apply to workspace**.

## Customizing entity page tabs <a href="#pinning-plugins" id="pinning-plugins"></a>

Users with the `Edit Entities` permission can pin, reorder, and hide plugins on an entity page. Plugins pinned this way appear as tabs at the top of the page, either on a single entity or across all entities of the same type.

Before a plugin can be pinned, it must be configured to include the relevant entity type in its context. For example, to pin a plugin on a Teams entity page, include the `team` entity type when registering the plugin in Cortex.

{% hint style="info" %}
System-level tabs are always visible by default but can be reordered. Most entity types only have the **Overview** tab, though some have more. For example, Teams entity pages include both the **Overview** and **Entities** tabs. Applicable plugins are also visible by default and are appended to any existing tab configuration.
{% endhint %}

Tab configurations saved at the individual entity level take precedence over configurations saved at the entity-type level. For example, if you customize tabs on the *Engineering* Teams page and later save a different tab configuration for all `team` entities, the *Engineering* page keeps its original configuration.

**To pin and reorder plugins**:

1. Navigate to the entity.
2. On the entity details page, click the **gear icon**.

   <div align="left" data-with-frame="true"><img src="/files/yus6BjEvgL4ig8VSCDlk" alt="The Gear icon near the upper-right corner of the page." width="400"></div>

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>When there are too many pinned tabs to fit across the page, the <strong>gear icon</strong> moves into the <em>Overflow</em> menu. Click the <strong>Overflow menu icon</strong> to access it.</p></div>

   The *Edit tabs* panel opens.
3. To reorder a plugin, hover over the **grip icon** and drag it to the desired position. To hide a plugin, click the **eye icon** next to it. Repeat as necessary.

   <div align="left" data-with-frame="true"><img src="/files/nUhEdHmYlJfmkv4xZh8H" alt="The Grip icon next to a plugin." width="250"></div>

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>There is no limit to the number of plugins you can pin to an entity page. If you have more pinned plugins than can fit across the page, the remaining tabs are accessible via the <em>Overflow</em> menu.</p></div>
4. To apply the layout to all entities of the same type, select the **Apply to entities of type service** checkbox.
5. Click **Save**. The plugin is pinned to the top of the entity details page.

   <div align="left" data-with-frame="true"><img src="/files/lCMnkJxyVjw7ZKOhoHhD" alt="The pinned plugin tabs." width="400"></div>


# Defining ownership

Ownership is a core use case of Cortex, as many organizations seek to establish accurate ownership of services, data, and other entities. Accurate ownership is foundational for accountability, incident response, security reviews, compliance, and developer productivity. Without clear ownership, critical issues can go unresolved and services can fall through the cracks.

{% hint style="success" %}
Avoid inefficient manual processes: Use [Cortex's ownership prediction model](#recommendation) to solve entity ownership quickly. Cortex automatically predicts entity owners so your developers don't waste time hunting down the wrong person.
{% endhint %}

Ownership can be defined by accepting Cortex's automated recommendations for ownership, pulled in from third-party integrations, or defined manually in the Cortex UI. Ownership can also be inherited from an entity's [fallback or append configuration](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/domains#domain-entity-descriptor).

Ownership drives which users will receive [notifications](/configure/settings/notifications) from Cortex, including alerts for on-call changes, when [verification](/configure/settings/entity-settings/verification) is needed on an assigned entity, when an entity is re-evaluated and its Scorecard changes, and more.

### Where to view entity owners

When viewing an entity, the owners appear in the metadata bar on the right side of the page:

<figure><img src="/files/bwhmguuVTrcYtTsSJgsv" alt="Entity owners appear on the right side of the entity page."><figcaption></figcaption></figure>

Click into the team name to view the team's entity page, including a list of members and a list of entities owned by that team.

You can [create or import the teams and users](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams#creating-a-team) who will be defined as owners for your entities.

## View entities without owners

There are a few ways to determine which of your entities in Cortex don't have owners assigned yet:

* Use the [Ownership tool](https://app.getcortexapp.com/admin/ownership) to see unowned entities and Cortex's automated recommendations for owners
  * Learn more about [using the Ownership tool](#cortex-automated-recommendations-for-ownership) below.
* View the [Executive Report](https://app.getcortexapp.com/admin/reports/executive), which lists unowned entities
* Launch an Ownership Verification Scorecard, which will automatically add tasks to your [Engineering homepage](/streamline/homepage) to ensure you add owners to entities
  * When [creating a Scorecard](/standardize/scorecards/create), select the Ownership Verification template.

## Define owners for entities

#### Types of owners

You can define owners based on:

* A team: The user is a member of a team that is listed as the owner of an entity.
  * We recommend setting up teams as owners. If you link a `group` in your YAML file from a different platform (such as Okta), the members of the team will be automatically updated in Cortex if anyone leaves your organization and is removed from your integrated identity provider.
* A user email address: The user is listed as the owner of an entity.
* [Fallback or append settings](#ownership-inheritance) configured in an entity's hierarchy.

#### Methods for defining ownership

Owners can be defined:

* By accepting Cortex's automated recommendations for owners, based on repository activity
* By pulling information from third-party integrations in the [entity descriptor YAML](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file)
  * Ownership can also be inherited via [fallback or append configuration](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/domains#domain-entity-descriptor).
* Directly in the Cortex UI
* Automatically if Cortex detects that an entity is owned by a team that does not yet exist in Cortex
  * If an entity's YAML references a team, but that team doesn't have a corresponding entry within Cortex, Cortex will automatically create a team. The team will include a label that says **Automatically created by Cortex**.

{% tabs %}
{% tab title="Recommendation" %}
**Cortex automated recommendations for ownership**

{% hint style="info" %}
**Research preview**

Not seeing the results you expect? This is an early version of the Ownership tool. Please send feedback and bug reports to us [via this form](https://docs.google.com/forms/d/e/1FAIpQLSdURosGQhMnmMCF7FA66v9DOdnk5rOSoK1SaUVGjpOy4ywt5g/viewform). Note the following considerations:

* This feature is supported for entities associated with a repository in GitHub, GitLab, or Azure DevOps. Mapping is done on per repository basis, so mapping teams owners to file paths within a monorepo is not supported.
* You must have teams configured in Cortex and team members must be [identity-mapped](/configure/settings/managing-users/identity-mapping) in order for Cortex to provide recommendations. The more teams and people you have mapped, the better the recommendations!
* Cortex analyzes the last 6 months of data, so if a repository has not had code changes within that time period, we will not have a recommendation.
* To accept or reject the recommended owner, the user must have the `Edit entities` permission.
* If you are using GitOps, you can view recommendations, but you cannot accept them from the UI.
  {% endhint %}

Cortex analyzes a repository and automatically recommends a team owner for entities that do not have an owner.

If an entity does not have an owner and Cortex has recommendations for who the owner should be, it will be flagged in the ownership tool under **Tools > Ownership**, in the "Owners" section of an entity details page overview, in the "Owners" sidebar link on an entity details page, and it will appear during the import process when [adding entities](/ingesting-data-into-cortex/entities-overview/entities/adding-entities).

**Review ownership recommendations in bulk**

Users can edit ownership on this page only if they have edit access for all entities. If a user only has edit access for some entities, they can accept ownership recommendations from an entity's details page, [as described below under "Review ownership recommendations per entity."](#review-ownership-recommendations-per-entity)

To review and assign ownership across all unowned entities:

1. In the main nav of Cortex, click **Tools > Ownership**.
   * A list of recommendations for ownership is displayed.\\

     <figure><img src="/files/5VNsCrn3JTXk4E3yYNcu" alt="The ownership tool lists entities and recommended owners."><figcaption></figcaption></figure>
2. Review and accept the recommended owners.
   * To apply all recommended owners: Ensure the checkboxes for all entities are selected, then at the top of the list, click **Accept recommendations**.
   * To apply selected owners: On the left side of the list, check the box next to the entities whose recommended owners you want to accept. When you are finished selecting, click **Accept recommendations** at the top of the list.

**Review ownership recommendations per entity**

Users can accept ownership recommendations for an entity if they have edit access for that specific entity, and if UI editing is enabled for that entity type under [**Settings > GitOps**](https://app.getcortexapp.com/admin/settings/gitops).

1. On an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details) next to the "Owners" field, click **Recommendations**.\
   ![](/files/mAF8gOD0BKuIwSFSRcLj)
2. Review the suggested owners. To accept a recommendation, check the box next to the recommended owner then click **Add owners**.\
   ![](/files/ar39gQNtqaYKuWgYcB2t)
   {% endtab %}

{% tab title="Entity descriptor" %}
**Define owners in the entity descriptor**

The `x-cortex-owners` field allows you to define a list of owners of type email or group.

```yaml
x-cortex-owners:
  # Groups can be pulled from various integrations
  - type: group
    name: my-team
    provider: CORTEX
    description: This is a description for this owner # optional
  - type: email
    email: user@example.com
    description: This is a description for this owner # optional
```

Cortex recognizes groups from the following integrations:

* [Azure Active Directory](/ingesting-data-into-cortex/integrations/entraid)
* [Azure DevOps](/ingesting-data-into-cortex/integrations/azuredevops)
* [BambooHR](/ingesting-data-into-cortex/integrations/bamboohr)
* [GitHub](/ingesting-data-into-cortex/integrations/github)
* [GitLab](/ingesting-data-into-cortex/integrations/gitlab)
* [Google](/ingesting-data-into-cortex/integrations/google)
* [Okta](/ingesting-data-into-cortex/integrations/okta)
* [Opsgenie](/ingesting-data-into-cortex/integrations/opsgenie)
* [ServiceNow](/ingesting-data-into-cortex/integrations/servicenow)
* [Workday](/ingesting-data-into-cortex/integrations/workday)

The value of `provider` is the name of the integration that the group is coming from. The available list is:

* ACTIVE\_DIRECTORY
* AZURE\_DEVOPS
* BAMBOO\_HR
* CORTEX: Use when referring to a team defined in Cortex; these teams do not map to identities from a connected integration.
* GITHUB
* GITLAB
* GOOGLE
* OKTA
* OPSGENIE
* SERVICE\_NOW
* WORKDAY

`name` is a case-sensitive field that refers to the following:

* if your provider is `CORTEX`, `name` corresponds to the `x-cortex-tag` for the Cortex team you want to identify as an owner
* otherwise, `name` corresponds to the upstream identifier of your owner from your integration
  {% endtab %}

{% tab title="Cortex UI" %}
**Define owners in the Cortex UI**

1. In Cortex, navigate to [**Catalogs > All entities**](https://app.getcortexapp.com/admin/entities).
2. Search for and select the entity whose ownership you want to edit.
3. In the upper right corner of the entity's page, click **Configure entity**.
   * If this option isn't displayed, make sure you have [enabled UI editing for entities](/configure/settings/gitops-settings#options-by-entity-type).
4. Click the **Owners** tab, then click **+Add** next to Teams or Users.

   <figure><img src="/files/QGlUK58xNNyKguDRPsEv" alt="In the Owners tab, click +Add."><figcaption></figcaption></figure>

   * Add team:
     * Select a team from the dropdown menu, then click **Add**.
   * Add user:
     * Select a user from the dropdown menu, then click **Add**.
     * You can also add a user who is not listed in Cortex. To do this, enter an email address into the **Email address** field, then click **Add**.
       {% endtab %}
       {% endtabs %}

### **Ownership inheritance**

Instead of defining ownership individually for every entity in your catalog, you can define ownership at the parent entity level and have that pass down to all of the entity's children. You can configure this in the Cortex UI while [creating a domain](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/domains#creating-domains-and-a-hierarchy) entity and adding owners to it, or while [creating an entity relationship](/ingesting-data-into-cortex/entities-overview/entities/defining-relationship-types#create-relationship-types-and-relationship-connections).

`inheritance` can also be defined in the entity descriptor under the `x-cortex-owners` block, as shown in the example below:

```yaml
openapi: 3.0.1
info:
  title: Payments
  description: This is my cool domain.
  x-cortex-tag: payments-domain
  x-cortex-type: domain
  x-cortex-owners:
      - type: GROUP
        name: cortexapps/engineering
        provider: GITHUB
        inheritance: APPEND
```

The `inheritance` type for each owner can be one of `APPEND`, `FALLBACK`, or `NONE`. If not set, inheritance is defaulted to `NONE`.

* `APPEND`: This owner is appended to the list of owners for all child entities.
* `FALLBACK`: In the case where a child has no valid owners, including fallbacks, this fallback will be assigned as the owner. Note that this only applies to a child entity down the hierarchy; it is not the fallback for the parent domain itself.
* `NONE`: This owner owns the domain, but not necessarily any of its children (no inheritance).

#### **Viewing the source of an inherited owner**

As your organization grows, ownership often becomes layered—entities inherit owners from parent domains, team relationships, and append or fallback rules. Follow the steps below to see exactly where each owner on an entity comes from.

{% hint style="info" %}
The **Inheritance chain** icon only appears next to owners that were inherited through an `APPEND` or `FALLBACK` rule. Cortex does not display the icon for direct owners—those defined on the entity itself— since they have no upstream source to trace.
{% endhint %}

1. Open any entity from your **Catalog**.
2. In the [metadata sidebar](/ingesting-data-into-cortex/entities-overview/entities/details#configuring-the-entity-metadata-sidebar), locate the **Owners** section.
3. Next to an owner, click the **Inheritance chain** icon.<br>

   <div align="left" data-with-frame="true"><figure><img src="/files/IT48s5PQv4qcBFfIDPbN" alt="The &#x27;Inheritance chain icon&#x27; is found within the Owners section in the metadata sidebar." width="375"><figcaption></figcaption></figure></div>

Cortex surfaces the source entity, the relationship type, and the rule (`APPEND` or `FALLBACK`) that propagated the owner to this entity. This makes it easy to understand why a team appears as an owner on an entity it doesn't directly own.

### Automatic discovery for AWS

Cortex can automatically discover ownership for your AWS resources using their `owner` tag. To enable this, make sure that your AWS resources have an owner tag matching the `x-cortex-tag` of the corresponding Cortex team and enable the **Sync ownership from AWS** toggle in [Settings > AWS](https://app.getcortexapp.com/admin/settings/aws?activeTab=Settings).

You can pull in all resources from AWS, and Cortex syncs those owners automatically based on their tags in AWS, allowing you to easily keep the resource owners up to date.

{% hint style="info" %}
Cortex syncs ownership from AWS every day at 6 am UTC.
{% endhint %}

## Remove incorrect owners

To remove incorrect ownership in Cortex, the steps depend on how the ownership was added and your current configuration. Expand the tile below to learn more.

<details>

<summary>Remove incorrect ownership</summary>

**If ownership was set via YAML (`x-cortex-owners`):**

* Update the `x-cortex-owners` block in your YAML to reference only the correct teams or individuals. Ensure that all referenced teams actually exist in Cortex.
* If you are using [GitOps](/configure/gitops), make sure the YAML is updated and merged to your main branch, then allow Cortex to re-sync. This will update the ownership in the UI to match your YAML.

**If ownership was added via API:**

* Use the [Create or update entity API](/api/readme/catalog-entities#post-api-v1-open-api) to completely replace the entity YAML, or the [Create or patch entity API](/api/readme/catalog-entities#patch-api-v1-open-api) to remove one or more owner and not change the rest of the entity YAML.

**If ownership is inherited from a domain or parent:**

* Check if the entity is a child of a domain or group with [ownership inheritance](#ownership-inheritance) enabled. If so, the parent’s owners may be appended to the entity.
* To remove inherited owners, edit the domain or parent’s owner inheritance setting (e.g., change from `Append` to `None`).

</details>

## Viewing entity ownership

### View your owned entities

<details>

<summary>See entities you own directly:</summary>

To see a list of entities you own directly, navigate to [**Catalogs > All entities**](https://app.getcortexapp.com/admin/entities) then click the **Mine** tab:\
![Click the "Mine" tab to view your entities](/files/WpiWLV2GANxmTr0j7ken)

</details>

#### Child team visibility

<details>

<summary>See your enties and entities owned by your team's child teams:</summary>

To see a list of entities you own directly and entities that are owned by your team's child teams:

1. Navigate to [**Catalogs > All entities**](https://app.getcortexapp.com/admin/entities).
   1. The list defaults to displaying the "Mine" tab, showing only the entities you own.
2. At the top of the list, click **Display**.
3. Enable the toggle next to **Include child teams**.\\

   <div align="left"><figure><img src="/files/cx1eyoqLrGiU5H8dwHwY" alt="Click &#x22;Display&#x22; then enable &#x22;Include child teams&#x22;." width="457"><figcaption></figcaption></figure></div>
4. Click **Done**.

</details>

### View a team's owned entities

<details>

<summary>You can filter the entity list by owner:</summary>

1. Under [**Catalogs > All entities**](https://app.getcortexapp.com/admin/entities), click the **All** tab.
2. In the upper right corner, click **Filter**.
3. In the left side of the filter modal, click **Teams**. Select teams from the dropdown, then click **Apply** at the bottom.\
   ![Click the "Mine" tab to view your entities](/files/r2WzOSfQ6ItZ34gY19pf)

</details>

### View entities owned by all teams within a hierachy

<details>

<summary>View entites owned by the parent and children teams:</summary>

Teams can exist within hierarchies. You can view a list of all entities that are owned by the parent team and all children teams in the hierarchy:

1. Navigate to the parent team's page in Cortex.
2. Click the **Entities** tab.
3. Click Display, then enable the toggle next to **Inherited Children**.\\

   <figure><img src="/files/17i96mF9oYHAEl6DNABp" alt=""><figcaption><p>While viewing owned entities, click Display then add inherited children to the view.</p></figcaption></figure>
4. Click **Done**.

The list will now display all entities owned by the parent and its children teams. Note that this setting does not persist when you navigate away from the page.

Read more about hierarchies in [the Teams documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams#understanding-hierarchies).

</details>

## Ownership settings in Cortex

Under [**Settings > Entities**](https://app.getcortexapp.com/admin/settings/entities), there are several settings relating to teams. Read more about these in the [Teams documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams#adjusting-team-settings).


# Defining relationship types

Relationship types allow you to define, manage, and visualize relationships between entities within your Cortex workspace, ensuring your organization's structures and dependencies are accurately represented.

## Understanding relationship types in Cortex

A relationship type defines how two entities relate to either other, and constrains the types of entities that can be the source and destination entities within the relationship.

Cortex provides multiple options for defining a relationship:

* **Entity relationship**: As described on this page, you can customize a relationship type (hierarchical or cyclical) between any entity type.
* **Team hierarchy**: You can define a hierarchical relationship between team entities. Teams can have [ownership](/ingesting-data-into-cortex/entities-overview/entities/ownership) over other entities. Learn more in [Add teams](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams#understanding-hierarchies).
* **Domain hierarchy**: You can define a hierarchical relationship between domain entities. You can also configure inheritance; the owner of an entity can be inherited from entities higher in the domain hierarchy. Learn more in [Add domains](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/domains#display-in-hierarchy).
* **Dependencies**: You can define a cyclical relationship between non-team entities. Learn more in [Defining dependencies](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/dependencies).

{% hint style="info" %}
Want to learn more? Check out the [Cortex Academy course on Catalogs, Entities, and Relationships](https://academy.cortex.io/courses/understanding-understanding-catalogs-entities-and-relationships), available to all Cortex customers and POVs.
{% endhint %}

### Common use cases of custom relationship types

<table><thead><tr><th width="162.05206298828125">Relationship type</th><th width="255.739501953125">Description</th><th width="144.203125">Source</th><th>Destination</th></tr></thead><tbody><tr><td>Repository</td><td>Mapping services to repositories to view the hierarchy of repos and the services they contain. For example, a service is linked to its code repository.</td><td>Service</td><td>Repository</td></tr><tr><td>Cloud account to resource</td><td>Associating cloud accounts (like AWS, Google Cloud Project, or Azure subscription) with their respective resources (such as EC2 instances or other cloud resources).</td><td><ul><li>AWS account</li><li>GCP</li><li>Azure subscription</li></ul></td><td><ul><li>AWS resources (e.g., EC2)</li><li>Google Cloud resources</li><li>Azure resources</li></ul></td></tr><tr><td>Service to environment</td><td>Linking services to their deployment environments.</td><td>Service</td><td>Environment</td></tr><tr><td>Monorepo</td><td>Mapping multiple services to a single repository.</td><td>Repository</td><td>Service</td></tr><tr><td>Service to endpoint</td><td>Associating services with their endpoints.</td><td>Service</td><td>Endpoint</td></tr><tr><td>Data center modeling</td><td>epresenting data centers and their relationships to other infrastructure components.</td><td>Data center</td><td>Component</td></tr></tbody></table>

Note that you should not create custom relationship types to represent ownership; [teams can be designated as owners of entities](#understanding-relationship-types-in-cortex).

## View relationship types

### View all configured relationship types

To view all relationship types, go to **Catalogs > All entities** then click the [Relationship types tab](https://app.getcortexapp.com/admin/entities?activeTab=relationships).

<figure><img src="/files/CDQYTN5L7bIbGG9urBw2" alt=""><figcaption><p>On the Entities page, click the "Relationship types" tab.</p></figcaption></figure>

To view the details of a specific relationship type, click its name from the list.

### View relationships on entity pages

If an entity belongs to a relationship, you can explore that context directly from its [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details). Select **Relationships** in the left sidebar to see all relationship types associated with the entity.

In the example below, the entity `California` belongs to a relationship called `Geography` . Relationships default to a **Graph view**, giving you a visual map of parent/child connections.

<figure><img src="/files/ylRCehi5PuTKkXaF4EPA" alt=""><figcaption></figcaption></figure>

From the graph, click any entity to view a quick summary of its metadata. Select **Go to entity** to navigate directly to that entity's detail page.

<figure><img src="/files/YEz3oeunR66kxlHX8nuJ" alt=""><figcaption></figcaption></figure>

Toggle to **Table view** to see the same data in a structured list. useful for quickly scanning or sorting related entities.

<figure><img src="/files/yXZCT08HLJ34fQqs0TRv" alt=""><figcaption></figcaption></figure>

## Manage relationship types

### Create relationship types and relationship connections

{% tabs %}
{% tab title="Cortex UI" %}
**Create relationship types in the Cortex UI**

1. Navigate to **Catalogs > All entities** then click the [Relationship types tab](https://app.getcortexapp.com/admin/entities?activeTab=relationships).
2. In the upper right corner, click **Create > Create new relationship type**. \\

   <figure><img src="/files/eEcumJuvOrDJRClfSzak" alt="In the upper right, click Create, then click &#x22;Create new relationship type&#x22;."><figcaption></figcaption></figure>
3. Configure the details and entity types:
   * **Name**: Enter a name for the relationship type.
   * **Identifier**: Enter a unique identifier, used to specify this relationship in YAML definitions for this relationship type.
   * **Description**: Add a description of the relationship to help others understand its purpose.
   * **Create relationship type catalog**: Enable this option to create a catalog for this relationship type.
   * **Source entity types**: Search for and select the entity types which will be the source for this relationship. Selecting no entity type means that all entity types are available as sources.
     * You can also customize the singular and plural wording of the entity types and the cardinality.
   * **Destination entity types**: Search for and select the entity types which will be the destination for this relationship. Selecting no entity type means that all entity types are available as destinations.
     * You can also customize the singular and plural wording of the entity types and the cardinality.
4. Configure the relationship constraints:
   * **Architecture**: If you are configuring hierarchical data, such as an org chart, we recommend choosing **Acyclical**. If you are configuring graph-like data, such as dependencies, we recommend choosing **Cyclical**.
   * **Definition location**: Configure where relationships can be defined — from destination entities, from source entities, or from either.
5. Configure metadata inheritance.
   * Enable the **Ownership** toggle to configure inheritance for the relationship type, then select how metadata will be inherited:
     * **Fallback**: This option uses the source's data only if the destination does not have anything defined.
     * **Append**: This option appends the source's data to the destination, even if it already has data defined.
     * Learn more about inheritance in [Defining ownership](/ingesting-data-into-cortex/entities-overview/entities/ownership#ownership-inheritance).
6. Click **Create**.

**Create relationship connections between entities in the UI**

After creating the relationship type, you can configure connections between entities in a relationship. You can do this via the [entity descriptor](#entity-descriptor) or in the UI, as described below:

1. Navigate to an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details). In the upper right corner, click **Configure entity**.
2. Click the **Relationships** link on the left.
3. At the top of the Relationship Type section, click the dropdown to select which relationship type you are configuring connections for.\\

   <div align="left"><figure><img src="/files/NkYg7thR5z2EAcueMTZm" alt="Click the dropdown under Relationships to choose a type." width="563"><figcaption></figcaption></figure></div>
4. After selecting the relationship type, you can search for and select entities in the Sources dropdown and in the Destinations dropdown.\
   ![Configure source or destination entities.](/files/b3c17Npb5VE1UEYJ8VBU)
5. At the bottom of the page, click **Save changes**.
   {% endtab %}

{% tab title="Entity descriptor" %}
**Create relationship connections between entities in the entity descriptor**

Relationship types must be [created in the Cortex UI](#cortex-ui) or via the API. Once a relationship type exists, you can define the connection in either the source or destination entity's YAML using the `x-cortex-relationships` tag.

In the example below, a source entity's YAML has a defined relationship type called `app-components` and has destination entities `production-ui` and `backend-app`.

```
  x-cortex-relationships:
  - type: app-components
    destinations:
    - tag: production-ui
    - tag: backend-app
```

Optionally, this can be configured in the YAML of the destination by replacing `source` with `destination` in the YAML above.

The relationship between entities in Cortex is based on the relationship being defined in the entity's YAML file; Cortex does not set hierarchies or relationships based on a YAML file's location in your repository.
{% endtab %}

{% tab title="API" %}
**Create relationship types via the API**

You can create, update, and delete relationship types using the [Cortex API](https://docs.cortex.io/api/readme/entity-relationship-types).

**Create relationship connections between entities via the API**

You can create, update, and delete relationships between entities using the [Cortex API](https://docs.cortex.io/api/readme/entity-relationships).
{% endtab %}
{% endtabs %}

### Edit relationship types

<details>

<summary>Edit relationship type</summary>

To edit an existing relationship type:

1. Navigate to **Catalogs > All entities** then click the [Relationship types tab](https://app.getcortexapp.com/admin/entities?activeTab=relationships).
2. In the row containing the relationship type, click the pen icon.\
   ![](/files/CGjkbyz26jD29xb41B9b)
3. Make any necessary changes, then at the bottom of the page, click **Save**.

</details>

### Delete relationship types

<details>

<summary>Delete relationship types</summary>

1. Navigate to **Catalogs > All entities** then click the [Relationship types tab](https://app.getcortexapp.com/admin/entities?activeTab=relationships).
2. Click the relationship type name.
3. On its details page, in the upper right corner, click **Remove**.\
   ![](/files/2sXiGfBJsL7u37tsFUJk)

</details>

## Entity relationship CQL

You can create Scorecard rules and write CQL queries based on entity relationships.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Entity relationship destinations</summary>

All recursive destinations an entity for a relationship type, with an optional depth parameter to expand results

**Definition**: `entity.destinations(relationshipType = "my-relationship")`

**Examples**

You could write a Scorecard rule to ensure that an entity has at least one destination with the "my-relationship" type:

```
entity.destinations(relationshipType = "my-relationship").length > 0
```

</details>

<details>

<summary>Entity relationship sources</summary>

All recursive sources an entity for a relationship type, with an optional depth parameter to expand results

**Definition**: `entity.sources(relationshipType = "my-relationship")`

**Examples**

You could write a Scorecard rule that ensures an entity has at least one source with the "my-relationship" type:

```
entity.sources(relationshipType = "my-relationship").length > 0
```

</details>


# Grouping entities

Groups are a tagging system that can be used to group a set of [entities](/ingesting-data-into-cortex/entities-overview/entities) together, enabling a variety of use cases including:

* Tagging
  * Use groups to segment entities.
  * For example, you could segment by tiers (`tier-0` to indicate high priority), type (backend, frontend, library, API), or language (Python, Java).
* Filtering throughout Cortex
  * Use groups to include or exclude certain entities from [Scorecards](/standardize/scorecards), [catalogs](/ingesting-data-into-cortex/catalogs), [CQL reports](/standardize/cql/cql-reports), and more.
  * For example, you may want a Scorecard to only apply to Python services or a catalog that only shows tier-0 services.
* Reporting
  * You could aggregate Scorecard scores by a specific group, such as a tier.
  * For example, viewing a Production Readiness Scorecard broken down by tier.

While viewing an entity, its groups are listed in the upper right side of the page:

<figure><img src="/files/GqzGlIQvGHwb3KxtG2Ue" alt="Groups appear in entity detail pages."><figcaption></figcaption></figure>

Click the group name to view a list of all other entities that are tagged with this group.

## How to define and apply groups

You can create new groups in an entity's YAML, directly in the Cortex UI, or via the API. When creating a new group, it is applied to the entity where you are creating the group.

Note the following considerations:

* If a group has been set in the entity descriptor YAML, an API call will **not** overwrite the existing value.
* Groups created via the API will not appear in the entity descriptor YAML.
* Groups created via the API cannot be removed via the Cortex UI.

{% tabs %}
{% tab title="Cortex UI" %}
To create a group in the UI:

1. Navigate to the entity that you want to apply a group to.
   * Click the magnifying glass icon at the bottom of the main nav, or click **Catalogs > All entities** and search for the entity from that page.
2. In the upper right corner of the entity page, click **Configure entity**.
3. Click into the **Groups** field.
   * To apply an existing group, type to search then click on the group.
   * To create a new group, type the group name into the field, then click the group name in the dropdown. The group will be created and applied to the entity.
4. At the bottom of the page, click **Save**.
   {% endtab %}

{% tab title="Entity descriptor" %}
Groups are defined as a list of tags.

```yaml
x-cortex-groups:
    - tier0
    - language:kotlin
```

Groups may not contain whitespace characters.
{% endtab %}

{% tab title="API" %}
You can use the API to add groups to an entity. See the [API documentation for groups here](/api/readme/groups).
{% endtab %}
{% endtabs %}

## Troubleshooting and FAQ

#### **When should I use groups instead of** [**custom data**](/ingesting-data-into-cortex/entities-overview/entities/custom-data)**?**

To determine whether or not to use groups or custom data, consider whether your use case would be considered "tagging" with a definite enum of values (`backend` vs `frontend`), or more freeform metadata `availability-zones: [east, west]`.

#### **What is the difference between `x-cortex-service-groups` and `x-cortex-groups`?**

There is no difference between these. `x-cortex-service-groups` has been deprecated in favor of `x-cortex-groups`, but the change is backward-compatible.


# Adding external documentation

Cortex is your source of truth to external docs. Instead of digging through wikis and other resources, you can aggregate docs on the relevant entities in Cortex in the following ways:

* [Adding links to an entity](#add-links-to-an-entity)
* [Displaying Swagger, OpenAPI, or AsyncAPI specs on an entity](#documentation-types)
* [Embedding git-driven markdown](#git-driven-markdown-docs)
* [Embedding dashboard charts](#embedded-dashboards)

If you have configured the [Slack integration](/ingesting-data-into-cortex/integrations/slack), you can use Slack Bot commands to [list an entity's docs links directly in Slack](#referencing-documentation-links-via-slack).

## View links on an entity

Links appear on an entity details page in the **Links & docs** section:

<figure><img src="/files/LUEpZHocWxZL7q6xYVda" alt=""><figcaption><p>Click "Links &#x26; docs" on the left side of an entity page.</p></figcaption></figure>

## Add links to an entity

On entities, you can add links to docs, runbooks, tech specs, dashboards, and more.

{% tabs %}
{% tab title="Cortex UI" %}
Before editing an entity via the UI, make sure that UI editing is enabled under [**Settings > GitOps**](https://app.getcortexapp.com/admin/settings/gitops).

1. In Cortex, navigate to an entity.
2. In the upper right corner of the entity details page, click **Configure entity**.
3. Click **Links** on the left side.
4. Click **+Add**.
5. Configure the link:
   * **Type**: Select the [type of link](#documentation-types).
     * To create a new type, enter the type name then click the name in the dropdown.
     * Learn more about [OpenAPI](#swagger-openapi), [AsyncAPI](#asyncapi-documentation), and [dashboard chart](#embed-dashboards) types below.
   * **Name**: Enter a name for the link.
   * **URL**: Enter the URL.
   * **Description**: Add a description of the link.
6. Click **Add**.
   {% endtab %}

{% tab title="Entity descriptor" %}
In the entity descriptor, add a list of `link` objects:

```yaml
x-cortex-link:
  - name: Human Readable Name
    type: runbook
    url: https://cortex.io
    description: Optional Description
```

`name`, `type`, and `url` are required.

The value of `type` can be defined based on your organization's preferences. Common examples include dashboard, documentation, healthcheck, logs, metrics, and runbook. See the sections below on this page describing [OpenAPI](#swagger-openapi), [AsyncAPI](#async-api), and [dashboard charts](#embed-dashboards).
{% endtab %}
{% endtabs %}

{% hint style="success" %}
You can quickly look up links using the [Cortex Slack Bot](#accessing-docs-links-via-slack).
{% endhint %}

### Git-driven markdown docs

Cortex automatically embeds markdown files from the `docs` folder of your repo or from the root directory. If Cortex detects relevant files, these docs show up under the **Links & docs** page in an entity's sidebar.

Cortex uses the [React markdown library](https://github.com/remarkjs/react-markdown) for rendering the documents.

## Documentation types

When [adding links to an entity](#add-links-to-an-entity), Cortex supports embedding OpenAPI or AsyncAPI specs, embedding specs from your repository, adding relative links to a repository that isn't associated with the entity, and embedding charts (from Datadog, Grafana, New Relic, or other sources). You can also create a custom type while [adding a link](#add-links-to-an-entity).

Cortex supports displaying Swagger/OpenAPI or AsyncAPI specs for each entity in the **API explorer** on an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details). You can also authorize your API and run queries directly in the API explorer.

### OpenAPI docs

You can use your [entity descriptor](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file) file as an OpenAPI spec file. As mentioned in the [documentation on entities](/ingesting-data-into-cortex/entities-overview/entities), the entity descriptor file extends the OpenAPI spec, so you can implement the spec directly in this file.

You may have existing or external specs you want to display in the API explorer from sources such as Swagger Hub or GitHub Raw URL. Add these to the JSON or YAML spec file under the [`x-cortex-link`](#add-links-to-an-entity) block, with the type `openapi`.

#### Embed specs from a git repository

If you have specs checked into your git repository, you can embed it by adding it as a relative URL with type `openapi`. For example:

```yaml
x-cortex-link:
  - name: My Spec
    type: OPENAPI
    url: ./docs/my-openapi-spec.yaml
```

#### **Relative links in another repo**

In addition to providing the ability to link to specs *within* the service repo, Cortex also allows for links that reference other git repositories that aren't necessarily associated with your entity but still within your organization.

{% hint style="success" %}
Power users can also specify a `branch` parameter between the second and the third colon separated group, in the form `github:org/repo:branch:path/to/file`. If this parameter is omitted, we will use the repository's default branch.
{% endhint %}

<details>

<summary>Relative link YAML examples</summary>

```yaml
x-cortex-link:
  - name: My GitHub Spec
    type: OPENAPI
    url: github:org/repo:path/to/file
```

```yaml
x-cortex-link:
  - name: My GitLab Spec
    type: OPENAPI
    url: gitlab:namespace/project:path/to/file
```

```yaml
x-cortex-link:
  - name: My Azure DevOps Spec
    type: OPENAPI
    url: azuredevops:project/repository:path/to/file
```

```yaml
x-cortex-link:
  - name: My Bitbucket Spec
    type: OPENAPI
    url: bitbucket:workspace/repo:path/to/file
```

</details>

#### Adding OpenAPI via the Cortex API

Using your [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag), you can also send your OpenAPI JSON or YAML file to the public [endpoint for managing OpenAPI documentation](/api/readme/docs) `/api/v1/catalog/documentation/openapi` for each of your entities. One API doc per entity can be uploaded and it will automatically show up as an `API Doc` entry in the dropdown in the API explorer.

The request body is the following, in JSON format. See API Docs for authentication details.

| Field    | Type   | Description                  |
| -------- | ------ | ---------------------------- |
| **spec** | string | The json or yaml as a string |

{% hint style="success" %}
Converting YAML or JSON to string You can use a lightweight utility like jq to take your yaml/json and generate a string that can be used for your request:

e.g. `$(cat my_file.yaml | jq -Rsa)`
{% endhint %}

### AsyncAPI docs

You may have existing or external specs you want to display in the API explorer from sources such as Swagger Hub or GitHub Raw URL. Add these to the JSON or YAML spec file under the [`x-cortex-link`](#add-links-to-an-entity) block, with the type `async_api`.

If you have specs checked into your Git repository, you can embed it by adding it as a relative URL with type `async_api`. For example:

```yaml
x-cortex-link:
  - name: My Spec
    type: ASYNC_API
    url: ./docs/my-spec.yml
```

### Embedded dashboards

Cortex supports embedding charts from [Datadog](/ingesting-data-into-cortex/integrations/datadog), [Grafana](/ingesting-data-into-cortex/integrations/grafana), or [New Relic](/ingesting-data-into-cortex/integrations/newrelic) directly into an entity for quick access. To view embedded charts, click the **Dashboard** page in the [entity's sidebar](/ingesting-data-into-cortex/entities-overview/entities/details#entity-details-sidebar).

You can add charts to an entity's YAML:

```yaml
x-cortex-dashboards:
  embeds:
    - type: datadog | grafana | newrelic (optional)
      url: https://example.com
```

* The `type` field is an optional enum of three types: `datadog`, `grafana`, or `newrelic`.
* The `url` field is the `src` value for the `iframe` embed generated by your dashboard tool.
  * You must use your tool's embed URL for individual charts.
  * The URL must be publicly accessible. Or, if you can access the iFrame via VPN, it should be accessible in Cortex while also on the VPN.

{% hint style="info" %}
Note that you can embed individual charts, not dashboards.

If you're using Grafana and seeing errors in your Grafana embeds, make sure your Grafana instance [has embeds enabled](https://grafana.com/docs/grafana/latest/administration/configuration/#allow_embedding).
{% endhint %}

#### Embed content from other sources

It is possible to display content from a source other than Datadog, Grafana, or New Relic. To do this, do not specify an option for the `type` field. The URL you add must be publicly accessible or provide cross-platform authentication for Cortex to view and display the iframe. For example, if the content is accessible via VPN, then you should be able to view it in Cortex while on the VPN.

## Accessing docs links via Slack

If you have configured the [Slack integration](/ingesting-data-into-cortex/integrations/slack), you can use [Slack Bot](/ingesting-data-into-cortex/integrations/slack#cortex-bot) commands to list documentation directly in Slack:

* `/slack links <tag-or-id>` to list all documentation links for an entity
* `/slack links [type] <tag-or-id>` to list specific types of documentation links for an entity

The `type` corresponds to the type of documentation (e.g., `openapi`, `documentation`, etc.). Replace `<tag-or-id>` with the [entity's tag or ID](/ingesting-data-into-cortex/entities-overview/entities#unique-identifiers-for-entities).

For example:

* To list all documentation links for an entity with ID `en29f044598b112345`, you could run the following command in Slack:\
  `/cortex links en29f044598b112345`
* To list the OpenAPI specs for an entity with tag `plugin-extension`, you could run the following command in Slack:\
  `/cortex links openapi plugin-extension`

{% hint style="info" %}
The Slack Bot `links` command works for any docs links listed under `x-cortex-links`. Note that it does not list the [charts](#embedded-dashboards) listed under `x-cortex-dashboards`.
{% endhint %}


# Adding deploy data via API

Getting deployment data into Cortex is critically important for both engineering insights and organizational success. It enables the use of [Eng Intelligence](/improve/eng-intelligence) to assess [DORA metrics](/improve/eng-intelligence/dashboards/dora-dashboard) and other KPIs to understand how quickly and efficiently your teams are shipping code. Deployment data also gives you the insight needed to create [Scorecards](/standardize/scorecards) and [Initiatives](/improve/initiatives) that promote process improvement across teams.

When you add deploy data to Cortex, it is visible on [entity pages](/ingesting-data-into-cortex/entities-overview/entities#adding-metadata-to-the-entity-descriptor), in Eng Intelligence [Metrics Explorer](/improve/eng-intelligence/metrics-explorer) and the [DORA](/improve/eng-intelligence/dashboards/dora-dashboard) and [Velocity Dashboards](/improve/eng-intelligence/dashboards/velocity-dashboard), in [executive reports](/improve/reports/executive-report), and can be accessed via [CQL](/standardize/cql).

## Add deployment data to Cortex

To get deploys into Cortex, you must use the [Add deployment for entity](/api/readme/deploys) API endpoint.

### Deploy data pipeline examples

In these examples, the repository secret or variable contains a valid [Cortex API key](/configure/settings/api-keys), and the repository name matches the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag).

<details>

<summary>GitHub Action</summary>

In this example, a repository secret called `CORTEX_TOKEN` contains a valid Cortex API key.

```yaml
name: Build and Deploy with Status Updates

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

env:
  CORTEX_API_URL: "https://api.getcortexapp.com/api/v1/catalog"
  PROJECT_NAME: "my-application"

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Validate Cortex token
      run: |
        if [ -z "${{ secrets.CORTEX_TOKEN }}" ]; then
          echo "ERROR: CORTEX_TOKEN secret not configured"
          exit 1
        fi
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: '18'
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
      
    - name: Run tests
      run: npm test
      
    - name: Build application
      run: npm run build
      
    - name: Deploy to staging
      run: |
        echo "Deploying to staging environment..."
        # Your deployment commands here
        # This might fail intentionally for demonstration

  # Guaranteed notification job that runs regardless of build-and-deploy outcome
  notify-result:
    runs-on: ubuntu-latest
    needs: build-and-deploy
    if: always() # This ensures the job runs regardless of build-and-deploy outcome
    
    steps:
    - name: Send deployment notification to Cortex
      run: |
        echo "Previous job result: ${{ needs.build-and-deploy.result }}"
        REPO_NAME=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]')
        echo "Using repo name: $REPO_NAME"
        
        # Check the status of the previous job
        if [ "${{ needs.build-and-deploy.result }}" == "success" ]; then
          TYPE="DEPLOY"
          STATUS="success"
          MESSAGE="All jobs completed successfully"
        elif [ "${{ needs.build-and-deploy.result }}" == "failure" ]; then
          TYPE="ROLLBACK"
          STATUS="failed"
          MESSAGE="Build and deploy job failed"
        elif [ "${{ needs.build-and-deploy.result }}" == "cancelled" ]; then
          TYPE="ROLLBACK"
          STATUS="cancelled"
          MESSAGE="Build and deploy job was cancelled"
        else
          TYPE="ROLLBACK"
          STATUS="skipped"
          MESSAGE="Build and deploy job was skipped"
        fi
        
        curl -L \
          --request POST \
          --max-time 30 \
          --retry 2 \
          --url "${{ env.CORTEX_API_URL }}/$REPO_NAME/deploys" \
          --header "Authorization: Bearer ${{ secrets.CORTEX_TOKEN }}" \
          --header "Content-Type: application/json" \
          --data "{
            \"customData\": {
              \"workflow\": \"${{ github.workflow }}\",
              \"run_id\": \"${{ github.run_id }}\",
              \"branch\": \"${{ github.ref_name }}\",
              \"final_status\": \"$STATUS\",
              \"message\": \"$MESSAGE\",
              \"actor\": \"${{ github.actor }}\",
              \"repository\": \"${{ github.repository }}\"
            },
            \"deployer\": {
              \"email\": \"${{ github.actor }}@users.noreply.github.com\",
              \"name\": \"${{ github.actor }}\"
            },
            \"environment\": \"staging\",
            \"sha\": \"${{ github.sha }}\",
            \"timestamp\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\",
            \"title\": \"Final deployment $STATUS - ${{ github.workflow }}\",
            \"type\": \"$TYPE\",
            \"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\"
          }"
```

</details>

<details>

<summary>GitLab pipeline</summary>

Make sure you have defined a CI/CD variable in GitLab that contains your Cortex API key, and ensure the repository you're running this in contains the package.json file.

If any stage in the pipeline fails, the entire pipeline fails and a ROLLBACK event is sent to Cortex.

```yaml
stages:
  - build
  - test
  - deploy
  - notify

variables:
  CORTEX_API_URL: "https://api.getcortexapp.com/api/v1/catalog"

# Global settings
image: node:18

build_job:
  stage: build
  script:
    - echo "Building application..."
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour

test_job:
  stage: test
  script:
    - echo "Running tests..."
    - npm test
  dependencies:
    - build_job

deploy_job:
  stage: deploy
  script:
    - echo "Deploying to staging..."
    # Your deployment commands here
    - sleep 2
    - echo "Deployment completed"
  dependencies:
    - build_job
  environment:
    name: staging

# This job always runs and reports pipeline status to Cortex
notify_cortex:
  stage: notify
  image: curlimages/curl:latest
  before_script:
    # Check if previous stages succeeded by examining needs
    - |
      if [ "$BUILD_JOB_STATUS" = "success" ] && [ "$TEST_JOB_STATUS" = "success" ] && [ "$DEPLOY_JOB_STATUS" = "success" ]; then
        PIPELINE_STATUS="success"
        DEPLOY_TYPE="DEPLOY"
        MESSAGE="Pipeline completed successfully"
      else
        PIPELINE_STATUS="failed"
        DEPLOY_TYPE="ROLLBACK"
        MESSAGE="Pipeline failed - one or more stages failed"
      fi
      
      echo "Pipeline Status: $PIPELINE_STATUS"
      echo "Deploy Type: $DEPLOY_TYPE"
      echo "Message: $MESSAGE"
  script:
    - |
      # Convert repo name to lowercase
      REPO_NAME=$(echo "$CI_PROJECT_NAME" | tr '[:upper:]' '[:lower:]')
      echo "Repository: $REPO_NAME"
      
      # Get current timestamp
      TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
      
      # Send notification to Cortex
      curl -L \
        --request POST \
        --max-time 30 \
        --retry 2 \
        --url "$CORTEX_API_URL/$REPO_NAME/deploys" \
        --header "Authorization: Bearer $CORTEX_TOKEN" \
        --header "Content-Type: application/json" \
        --data "{
          \"customData\": {
            \"pipeline_id\": \"$CI_PIPELINE_ID\",
            \"job_id\": \"$CI_JOB_ID\",
            \"branch\": \"$CI_COMMIT_REF_NAME\",
            \"pipeline_status\": \"$PIPELINE_STATUS\",
            \"message\": \"$MESSAGE\",
            \"pipeline_url\": \"$CI_PIPELINE_URL\",
            \"project_path\": \"$CI_PROJECT_PATH\"
          },
          \"deployer\": {
            \"email\": \"$GITLAB_USER_EMAIL\",
            \"name\": \"$GITLAB_USER_NAME\"
          },
          \"environment\": \"staging\",
          \"sha\": \"$CI_COMMIT_SHA\",
          \"timestamp\": \"$TIMESTAMP\",
          \"title\": \"Pipeline $PIPELINE_STATUS - $CI_PROJECT_NAME\",
          \"type\": \"$DEPLOY_TYPE\",
          \"url\": \"$CI_PIPELINE_URL\"
        }"
      
      if [ $? -eq 0 ]; then
        echo "Successfully notified Cortex"
      else
        echo "Failed to notify Cortex, but continuing..."
      fi
  needs:
    - job: build_job
      artifacts: false
    - job: test_job  
      artifacts: false
    - job: deploy_job
      artifacts: false
  when: always
```

</details>

<details>

<summary>Azure DevOps</summary>

In this example, a variable called `CORTEX_TOKEN` contains a valid Cortex API key.

```yaml
trigger:
  branches:
    include:
      - main
      - develop

pr:
  branches:
    include:
      - main

variables:
  CORTEX_API_URL: 'https://api.getcortexapp.com/api/v1/catalog'

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Build
  displayName: 'Build Stage'
  jobs:
  - job: BuildJob
    displayName: 'Build Application'
    steps:
    - task: NodeTool@0
      inputs:
        versionSpec: '18.x'
      displayName: 'Install Node.js'

    - script: |
        echo "Building application..."
        npm ci
        npm run build
      displayName: 'Build Application'

    - publish: dist
      artifact: BuildArtifacts
      displayName: 'Publish Build Artifacts'

- stage: Test
  displayName: 'Test Stage'
  dependsOn: Build
  jobs:
  - job: TestJob
    displayName: 'Run Tests'
    steps:
    - task: NodeTool@0
      inputs:
        versionSpec: '18.x'
      displayName: 'Install Node.js'

    - script: |
        echo "Running tests..."
        npm ci
        npm test
      displayName: 'Run Tests'

- stage: Deploy
  displayName: 'Deploy Stage'
  dependsOn: Test
  jobs:
  - job: DeployJob
    displayName: 'Deploy to Staging'
    steps:
    - script: |
        echo "Deploying to staging..."
        sleep 2
        echo "Deployment completed"
      displayName: 'Deploy Application'

- stage: Notify
  displayName: 'Notify Cortex'
  dependsOn: 
    - Build
    - Test
    - Deploy
  condition: always()
  jobs:
  - job: NotifyJob
    displayName: 'Send Cortex Notification'
    steps:
    - checkout: none
    
    - bash: |
        echo "Build Stage Result: $(stageDependencies.Build.BuildJob.result)"
        echo "Test Stage Result: $(stageDependencies.Test.TestJob.result)"
        echo "Deploy Stage Result: $(stageDependencies.Deploy.DeployJob.result)"
        
        # Determine overall pipeline status
        BUILD_RESULT="$(stageDependencies.Build.BuildJob.result)"
        TEST_RESULT="$(stageDependencies.Test.TestJob.result)"
        DEPLOY_RESULT="$(stageDependencies.Deploy.DeployJob.result)"
        
        if [ "$BUILD_RESULT" = "Succeeded" ] && [ "$TEST_RESULT" = "Succeeded" ] && [ "$DEPLOY_RESULT" = "Succeeded" ]; then
          PIPELINE_STATUS="success"
          DEPLOY_TYPE="DEPLOY"
          MESSAGE="Pipeline completed successfully"
        else
          PIPELINE_STATUS="failed"
          DEPLOY_TYPE="ROLLBACK"
          MESSAGE="Pipeline failed - one or more stages failed (Build: $BUILD_RESULT, Test: $TEST_RESULT, Deploy: $DEPLOY_RESULT)"
        fi
        
        echo "Pipeline Status: $PIPELINE_STATUS"
        echo "Deploy Type: $DEPLOY_TYPE"
        echo "Message: $MESSAGE"
        
        # Convert repo name to lowercase (extract from full repository name)
        REPO_NAME=$(echo "$(Build.Repository.Name)" | cut -d'/' -f2 | tr '[:upper:]' '[:lower:]')
        echo "Repository: $REPO_NAME"
        
        # Get current timestamp
        TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
        
        # Get deployer information
        DEPLOYER_EMAIL="${BUILD_REQUESTEDFOREMAIL:-devops@company.com}"
        DEPLOYER_NAME="${BUILD_REQUESTEDFOR:-Azure DevOps}"
        
        # Send notification to Cortex
        curl -L \
          --request POST \
          --max-time 30 \
          --retry 2 \
          --url "$(CORTEX_API_URL)/$REPO_NAME/deploys" \
          --header "Authorization: Bearer $(CORTEX_TOKEN)" \
          --header "Content-Type: application/json" \
          --data "{
            \"customData\": {
              \"pipeline_id\": \"$(Build.BuildId)\",
              \"build_number\": \"$(Build.BuildNumber)\",
              \"branch\": \"$(Build.SourceBranchName)\",
              \"pipeline_status\": \"$PIPELINE_STATUS\",
              \"message\": \"$MESSAGE\",
              \"build_url\": \"$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)\",
              \"project\": \"$(System.TeamProject)\",
              \"repository\": \"$(Build.Repository.Name)\"
            },
            \"deployer\": {
              \"email\": \"$DEPLOYER_EMAIL\",
              \"name\": \"$DEPLOYER_NAME\"
            },
            \"environment\": \"staging\",
            \"sha\": \"$(Build.SourceVersion)\",
            \"timestamp\": \"$TIMESTAMP\",
            \"title\": \"Pipeline $PIPELINE_STATUS - $(Build.Repository.Name)\",
            \"type\": \"$DEPLOY_TYPE\",
            \"url\": \"$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)\"
          }"
        
        if [ $? -eq 0 ]; then
          echo "Successfully notified Cortex"
        else
          echo "Failed to notify Cortex, but continuing..."
        fi
      displayName: 'Send Cortex Notification'
      env:
        CORTEX_TOKEN: $(CORTEX_TOKEN)
```

</details>

<details>

<summary>Jenkins</summary>

In this example, it is assumed that the Jenkins job is associated with a repository. It uses the repository name to match with the Cortex entity tag. The job also assumes that you have defined a Global Credential called `CORTEX_TOKEN` that contains a valid Cortex API key.

```yaml
pipeline {
    agent any
    
    environment {
        CORTEX_API_URL = "https://api.getcortexapp.com/api/v1/catalog"
    }
    
    stages {
        stage('Build') {
            steps {
                script {
                    echo "Building application..."
                }
                sh '''
                    node --version
                    npm --version
                    npm ci
                    npm run build
                '''
            }
            post {
                success {
                    script {
                        env.BUILD_STAGE_RESULT = 'SUCCESS'
                    }
                }
                failure {
                    script {
                        env.BUILD_STAGE_RESULT = 'FAILURE'
                    }
                }
            }
        }
        
        stage('Test') {
            steps {
                script {
                    echo "Running tests..."
                }
                sh 'npm test'
            }
            post {
                success {
                    script {
                        env.TEST_STAGE_RESULT = 'SUCCESS'
                    }
                }
                failure {
                    script {
                        env.TEST_STAGE_RESULT = 'FAILURE'
                    }
                }
            }
        }
        
        stage('Deploy') {
            steps {
                script {
                    echo "Deploying to staging..."
                    sh '''
                        sleep 2
                        echo "Deployment completed"
                    '''
                }
            }
            post {
                success {
                    script {
                        env.DEPLOY_STAGE_RESULT = 'SUCCESS'
                    }
                }
                failure {
                    script {
                        env.DEPLOY_STAGE_RESULT = 'FAILURE'
                    }
                }
            }
        }
    }
    
    post {
        always {
            script {
                notifyCortex()
            }
        }
    }
}

def notifyCortex() {
    try {
        echo "Build Stage Result: ${env.BUILD_STAGE_RESULT ?: 'SKIPPED'}"
        echo "Test Stage Result: ${env.TEST_STAGE_RESULT ?: 'SKIPPED'}"
        echo "Deploy Stage Result: ${env.DEPLOY_STAGE_RESULT ?: 'SKIPPED'}"
        
        // Determine overall pipeline status
        def buildResult = env.BUILD_STAGE_RESULT ?: 'SKIPPED'
        def testResult = env.TEST_STAGE_RESULT ?: 'SKIPPED'
        def deployResult = env.DEPLOY_STAGE_RESULT ?: 'SKIPPED'
        
        def pipelineStatus
        def deployType
        def message
        
        if (buildResult == 'SUCCESS' && testResult == 'SUCCESS' && deployResult == 'SUCCESS') {
            pipelineStatus = 'success'
            deployType = 'DEPLOY'
            message = 'Pipeline completed successfully'
        } else {
            pipelineStatus = 'failed'
            deployType = 'ROLLBACK'
            message = "Pipeline failed - one or more stages failed (Build: ${buildResult}, Test: ${testResult}, Deploy: ${deployResult})"
        }
        
        echo "Pipeline Status: ${pipelineStatus}"
        echo "Deploy Type: ${deployType}"
        echo "Message: ${message}"
        
        // Convert repo name to lowercase (extract from job name)
        def repoName = env.JOB_NAME.tokenize('/')[0].toLowerCase()
        echo "Repository: ${repoName}"
        
        // Get Git commit SHA and branch
        def gitCommit = sh(
            script: 'git rev-parse HEAD',
            returnStdout: true
        ).trim()
        
        def gitBranch = sh(
            script: 'git rev-parse --abbrev-ref HEAD',
            returnStdout: true
        ).trim()
        
        // Get current timestamp
        def timestamp = sh(
            script: 'date -u +"%Y-%m-%dT%H:%M:%SZ"',
            returnStdout: true
        ).trim()
        
        // Escape JSON special characters in message
        def escapedMessage = message.replaceAll('"', '\\\\"').replaceAll("'", "\\\\'")
        
        // Get deployer information
        def deployerEmail = env.BUILD_USER_EMAIL ?: 'jenkins@company.com'
        def deployerName = env.BUILD_USER ?: 'Jenkins'
        
        // Build JSON payload
        def jsonPayload = """
        {
            "customData": {
                "pipeline": "${env.JOB_NAME}",
                "build_number": "${env.BUILD_NUMBER}",
                "branch": "${gitBranch}",
                "pipeline_status": "${pipelineStatus}",
                "message": "${escapedMessage}",
                "build_url": "${env.BUILD_URL}",
                "jenkins_url": "${env.JENKINS_URL}"
            },
            "deployer": {
                "email": "${deployerEmail}",
                "name": "${deployerName}"
            },
            "environment": "staging",
            "sha": "${gitCommit}",
            "timestamp": "${timestamp}",
            "title": "Pipeline ${pipelineStatus} - ${env.JOB_NAME}",
            "type": "${deployType}",
            "url": "${env.BUILD_URL}"
        }
        """
        
        // Send notification to Cortex
        withCredentials([string(credentialsId: 'CORTEX_TOKEN', variable: 'CORTEX_TOKEN')]) {
            def curlResult = sh(
                script: """
                    curl -L \\
                      --request POST \\
                      --max-time 30 \\
                      --retry 2 \\
                      --url "${env.CORTEX_API_URL}/${repoName}/deploys" \\
                      --header "Authorization: Bearer \${CORTEX_TOKEN}" \\
                      --header "Content-Type: application/json" \\
                      --data '${jsonPayload}' \\
                      --write-out "%{http_code}" \\
                      --silent \\
                      --output /dev/null
                """,
                returnStdout: true
            ).trim()
            
            if (curlResult == '200' || curlResult == '201') {
                echo "Successfully notified Cortex (HTTP ${curlResult})"
            } else {
                echo "Failed to notify Cortex (HTTP ${curlResult}), but continuing..."
            }
        }
        
    } catch (Exception e) {
        echo "Failed to send Cortex notification: ${e.getMessage()}"
        // Don't fail the build if notification fails
    }
}
```

</details>

### Add custom data to deployments

Adding a `customData` object to your API call allows you the flexibility to add metadata that is important to your organization.

If custom data is included for a deploy, you can view it under "CI/CD > Deploys" on an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details). Click the "Details" drop-down to expand and view the custom data:

<figure><img src="/files/9hmXDOcJXE7KEMek1NNH" alt=""><figcaption></figcaption></figure>

## Viewing deploy data

### View deployments on entity pages

Deployment information appears in several places on an entity page:

* While viewing an entity page, you can see last deployment information near the top of the page:

  <figure><img src="/files/ffZLRa6qZMh0Yr8yaNo1" alt=""><figcaption><p>Deployment information appears near the top of an entity details page.</p></figcaption></figure>
* Near the bottom of an entity page, deploys will also appear under "Recent activity."
* In the left sidebar of an entity, click **Events**. This page includes:

  * A visual chart of deploys.
    * By default the chart shows data from the last month. Click the Last month dropdown in the upper right to change the timeframe.
  * All recent events for the entity. In the upper right corner of the events list, click **Filter** to select and apply filters for this list. You can choose to only view the `deploy` event types. \\

  <figure><img src="/files/4qDXZjRhCpZyuZLNaBj6" alt=""><figcaption><p>On an entity page, click "Events" in the sidebar to view recent events.</p></figcaption></figure>

### View deployments in Eng Intelligence

When you send deploy data into Cortex, you can use this information in [Eng Intelligence](/improve/eng-intelligence) reporting to gain insight into your [deploy metrics](/improve/eng-intelligence#deploy-metrics). Deploy metrics include average number of deploys per week and deploy change failure rate.

In Eng Intelligence, click into an entity to open a side panel with a historical performance graph.

Read more about using [Eng Intelligence in the documentation](/improve/eng-intelligence).

### Use deployment data in CQL and Scorecards

You can use deploy data to write rules for [Scorecards](/standardize/scorecards) and to create [CQL reports](/standardize/cql/cql-reports).

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Deploys</summary>

Deploys added to an entity through the [public API](/api/readme/deploys).

**Definition:** `deploys(lookback: Duration, types: List): List`

**Example**

In a Scorecard, you can write a rule to check whether an entity had fewer than 5 bug fixes in the last month:

```
deploys(lookback = duration("P1M"), types = ["DEPLOY"]).filter((deploy) => deploy.customData != null AND deploy.customData.get("bugFix") == true).length = 2
```

Write a rule to verify that there was, on average, less than 1 rollback for every 4 deploys in the past month:

```
deploys(lookback=duration("P1M"),types=["ROLLBACK"]).length / deploys(lookback=duration("P1M"),types=["DEPLOY", "ROLLBACK", "RESTART"]).length < 0.25
```

</details>


# Adding custom data

Custom data extends the out-of-the-box metadata that Cortex provides via integrations, enhancing your use of catalogs and augmenting details available for your entities. This data can also be used to write CQL queries and [Scorecard rules](/standardize/scorecards).

Custom data can be defined manually in the [entity descriptor](#editing-the-entity-descriptor), added to entities programmatically via a [REST API](#adding-custom-data-via-the-cortex-api), or sent through a webhook. To learn about sending data via webhook, see [Custom webhook integrations](/ingesting-data-into-cortex/integrations/webhook).

### Custom data vs. Custom metrics

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

* **Custom data** should be used when you need to attach static or slowly changing metadata to entities, such as deployment environments, compliance statuses, or other descriptive attributes. It is best for enriching entity details, reporting, and Scorecard rules based on entity attributes. Learn more below in [Use cases](#use-cases).
  * It is not ideal for tracking dynamic or time-sensitive information, as new data will overwrite previous values for the same key.
* **Custom metrics** should be used to track time series or trending data, such as incident counts, SLOs, or any metric that changes over time and needs to be visualized in charts or analyzed in Eng Intelligence. Learn more in [Custom metrics](/improve/eng-intelligence/custom-metrics).
  * Custom metrics are designed for analytics and can be used in dashboards, entity pages, and Scorecards.

## Defining custom data

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

* In the entity descriptor
  * This is optimal for low-volume, human-maintained data because it requires updating the entity's YAML when the data changes.
* Via a `POST` REST API endpoint
  * Using a [REST API](#api) is a better option for data that comes from an automated process, like a CI/CD pipeline.
* A [webhook](/ingesting-data-into-cortex/integrations/webhook).
  * This can be done without auth or an explicit [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) in the URL if you do not have access to the Cortex tag or the ability to add authentication headers.

{% tabs %}
{% tab title="Entity descriptor" %}
**Editing the entity descriptor**

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

The simplest way to describe information in the YAML is to define an object.

```yaml
x-cortex-custom-metadata:
  key-example: value-example
  arbitrary-custom-data: hippocampus
  regions-of-brain:
    value: 3
    description: cerebrum, cerebellum, brainstem
  cognition: true
```

| Field   | Description                                                                                    | Required |
| ------- | ---------------------------------------------------------------------------------------------- | :------: |
| `key`   | Key or title for the custom data. Anything defined **before** the `:` will serve as the `key`. |   **✓**  |
| `value` | Value for the custom data. Anything defined **after** the `:` is the `value`.                  |   **✓**  |

Custom data can be of any type, including scalars (strings, numbers, booleans), objects, and lists.

When you add custom data to an entity's YAML, you'll see the `key` and `value` pairs on an entity's **Custom data** page.

Custom data added via entity descriptor will display with a `YAML` tag.

**Adding descriptions**

You can add a description to data by explicitly defining it along with the `key` and `value` pairs. While `key` and `value` pairs can be defined with any terms when a description is not added, `value:` must explicitly be defined when a description is included.

```yaml
x-cortex-custom-metadata:
  regions-of-brain:
    value: 3
    description: cerebrum, cerebellum, brainstem
  brain-hemispheres:
    value: 2
    description: The brain has a left and a right hemisphere.
```

| Field         | Description                                                                                    | Required |
| ------------- | ---------------------------------------------------------------------------------------------- | :------: |
| `key`         | Key or title for the custom data. Anything defined **before** the `:` will serve as the `key`. |   **✓**  |
| `value`       | Value for the key; should be defined explicitly with `value:`                                  |   **✓**  |
| `description` | Description of the custom data                                                                 |   **✓**  |

Note: While the `description` field is always optional, it is technically "required" to add a description to custom data.
{% endtab %}

{% tab title="API" %}
**Adding custom data via the Cortex API**

You can pipe custom data directly into Cortex by `POST`ing to `/api/v1/catalog/{tag}/custom-data` where `{tag}`is the `x-cortex-tag` for a given entity.

The request body requires the following in JSON format:

| Field         | Type   | Description                      | Required |
| ------------- | ------ | -------------------------------- | :------: |
| `key`         | string | Key or title for the custom data |   **✓**  |
| `value`       | object | Value for the custom data        |   **✓**  |
| `description` | string | Description of the custom data   |          |

See the [API docs ](/api/readme/custom-data)for authentication details.

If a key has already been set through the [entity descriptor](#editing-the-entity-descriptor), an API call will **NOT** overwrite the existing value. Instead, it will simply return the existing value.

{% hint style="warning" %}
If a `key` is defined in the entity descriptor, the API cannot override the key. You'll see `YAML` as the `source` value in the response body if you encounter this situation.
{% endhint %}

To explicitly overwrite values set in the YAML file, use the `force=true` flag as a query parameter.

{% hint style="info" %}
If you find yourself using the `force` flag, it may be better to remove the field from the YAML file or update the value in the `cortex.yaml` file instead to maintain the source of truth.
{% endhint %}

Custom data added via API will display with a `API` tag.

**Bulk upload entity keys**

You can use the bulk upload endpoint to upload multiple keys for one or more entities.

`PUT` data in the following format to `/api/v1/catalog/custom-data`:

```json
{
  "values": {
    "<entity-tag>": [
      {
        "key":"example-key",
        "value":"example value",
        "description":"A description of these data."
      }
    ],
    "<another-entity-tag>": [
      {
        "key":"example",
        "value":{
          "my-data":"my-value",
          "complex": "data",
          "v": 0
        }
      }
    ]
  }
}
```

You can include multiple `key` and `value` objects for each tag. The object conforms to the same shape as the single upload API.
{% endtab %}

{% tab title="Webhook" %}
Learn more in [Custom webhook integrations](/ingesting-data-into-cortex/integrations/webhook).
{% endtab %}
{% endtabs %}

### Data source hierarchy

Cortex applies a data source hierarchy to determine how to handle a case where the same `key` is defined from multiple sources.

* The [entity descriptor](#editing-the-entity-descriptor) is the source of truth. If a key is defined there, the API or webhooks cannot override the key.
* The [API](#adding-custom-data-via-the-cortex-api) and [webhook](#webhook) approaches are at the same level and can override each other.

You can override keys defined in the YAML by adding a `force=true` parameter when using an API, but when the entity descriptor is eventually re-processed, the data provided via the API will be overwritten.

## Use cases

### Cataloging

Catalogs contain a lot of useful metadata about entities, including ownership and data from integrations. However, you may have your own custom fields that you want to include that would make exploring the catalog easier.

These can include things like:

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

{% hint style="success" %}
If the answers to these questions fit a pre-enumerated list, consider using [groups](/ingesting-data-into-cortex/entities-overview/entities/groups). Groups are displayed on entity detail pages and can easily be applied in catalog filters.

Custom data for cataloging makes the most sense when the data is more flexible.
{% endhint %}

Custom data can then be queried against by using the [Query builder](/standardize/cql#the-query-builder-tool), explored with [CQL reports](/standardize/cql/cql-reports), or viewed on an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details).

### Scorecards

Cortex makes it easy to write [Scorecard rules](/standardize/scorecards) based on custom data that exists in your catalogs. When adding a rule, you can select **Custom data** from **Choose an integration** in the form editor and follow the flow. Cortex will automatically supply variables based on the custom data you've defined.

{% hint style="success" %}
Using the [custom data API](/api/readme/custom-data) to push data into Cortex and extend your Scorecards. You can send entire JSON payloads and use `jq` to process them in a Scorecard, or use it as an input to a custom `OPA Policy` as a Scorecard rule.
{% endhint %}


# Viewing discovered entities

You may have over a hundred repositories in GitHub, and eventually, you will likely import all of them into Cortex. This much information can make it difficult to know at a glance that all repositories are accounted for and all new projects are being imported into and tracked within Cortex.

The discovered entities list (formerly known as the discovery audit) guarantees confidence in your catalogs by listing all changes that Cortex has detected. Cortex compares everything that exists within the system to what it discovers within your git tool, APM tool, Kubernetes cluster, and other crucial integrations, giving you insight into changes happening across your environments.

## View the discovered entities

You can view discovered entities under **Catalogs > All entities** in the [Discovered entities tab](https://app.getcortexapp.com/admin/entities?activeTab=discovered).

<figure><img src="/files/BwnEq9mevYRNXSiO9q95" alt="Navigate to Catalogs < All entities, then click the Discovered entities tab."><figcaption></figcaption></figure>

On this page, see a list of recent changes in your environment that aren't yet reflected in Cortex, including newly created repositories, services, and resources discovered from your integrations.

### Filter the discovered entities list

The first time you view the discovered entities list, there may be a lot to review. To narrow the scope of your list and start with changes that are the highest priority for you, search or filter the list by integration or entity type.

* To search, enter text into the search bar in the upper right corner of the list.
* To filter, click **Filter** in the upper right corner of the list. Select your filtering criteria, then click **Apply**.\
  ![](/files/yDpdWfkq8ddmCZxWEEJy)

## Importing and removing entities

Cortex will tag detected changes to signify whether an entity or repository has been discovered, archived, or deleted.

You can import, delete, or ignore the entities listed in Discovery audit.

### Import discovered entities

If Cortex detects a new service or resource, you can import it directly from this page:

1. Click `+` in the row containing the new entity:

   <figure><img src="/files/M7V0aAK2h1wPfnRS5Aq9" alt="Click + at the end of the row."><figcaption></figcaption></figure>
2. Configure the entity details.
   * For detailed instructions on creating a new entity, see the relevant docs page for the entity type: [Services](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services), [Domains](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/domains), [Custom entities](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/entity-types).
3. Click **Confirm import**.

### Delete discovered entities

If Cortex no longer detects a given entity, you also have the ability to delete that entity or repository directly from this page:

1. Click the **trash can icon** in the row containing the entity:\\

   <figure><img src="/files/fg6zDAvG5z3LhQidNXUr" alt="Click the trash icon at the end of the row."><figcaption></figcaption></figure>
2. In the confirmation window, click **Delete**.
   * The confirmation window gives you the opportunity to review all potentially impacted services before deleting, so you don’t unintentionally remove something from Cortex.

### Ignore discovered entities

If an event appears within the discovered entities list, but is irrelevant — for example, a test project that doesn’t need to be imported into Cortex — you can ignore it:

* Click the hide icon in the row containing the entity:\\

  <figure><img src="/files/TT9qu1PpWm36O45QZpb8" alt="Click the eye icon to ignore an entity."><figcaption></figcaption></figure>

The entity will now appear in the **Ignored** tab. The ignore action is persistent, so the event won’t appear again within the discovered list.

From the ignored list, you can move the entity back to the **Discovered** tab by clicking the eye icon.

## Troubleshooting and FAQ

#### Why do I not see all of my services from my APM provider in the discovered entities list?

Cortex supports a subset of integrations within the discovered entities list:

* Datadog
* ECS
* Version control (Azure DevOps, Bitbucket, GitHub, GitLab)
* Instana
* Kubernetes
* Lighstep
* New Relic


# Archiving entities

Archiving an entity allows you to remove it from active use while preserving its history and context.

You can configure Cortex to automatically archive entities when they are no longer detected in your integrations or when their corresponding YAML files are deleted. We recommend enabling this feature to keep your data up-to-date without manual effort. Learn more in [Auto archiving entities](/configure/settings/entity-settings/auto-archive).

It's also possible to manually archive entities in the Cortex UI or via the Cortex API, as described below.

## How to archive and unarchive entities

To archive entities, your user or API key must have the `Archive entities` permission. To unarchive entities, your user or API key must have the `Configure entities` permission.

{% tabs %}
{% tab title="Cortex UI" %}

1. Navigate to an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details) in Cortex.
2. Click the 3 dots menu at the top of the page, then click **Archive entity**.\ <img src="/files/THQljVWOZAixZUHWYoaQ" alt="" data-size="original">
3. In the confirmation window, click **Archive**.\
   ![](/files/WW6ol9L6TRWnps0HlXfr)

To un-archive an entity:

1. Navigate to the archived [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details) in Cortex.
2. Click the 3 dots menu at the top of the page, then click **Unarchive entity**.
3. In the confirmation window, click **Restore**.
   {% endtab %}

{% tab title="API" %}
See the API documentation on [archiving an entity](/api/readme/catalog-entities#put-api-v1-catalog-tagorid-archive) and [unarchiving an entity](/api/readme/catalog-entities#put-api-v1-catalog-tagorid-unarchive).
{% endtab %}
{% endtabs %}

## How archived entities are handled in Cortex

Archived entities are not included in the following Cortex features:

* [Scorecards](/standardize/scorecards) and [Initiatives](/improve/initiatives)
* [Reports](/improve/reports)
* [Eng Intelligence](/improve/eng-intelligence)
* [Cortex Query Language (CQL) ](/standardize/cql)features, including CQL reports and query builder
* [Relationship graphs](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph)
* [Workflows](/streamline/workflows)

### The "All entities" and Catalogs pages

By default, archived entities do not appear in the lists on "All entities" or in catalogs, but you can choose to include archived entities in your view.

To include archived entities:

1. Click **Display** at the top of the list.\
   ![](/files/5eYQ6qHAIc9arUj2ZW1I)
2. Toggle on the setting for **Show archived**.

Note that this setting is not persistent when you navigate away from the page.

### An entity details page

On an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details), if a related dependency, child entity, or parent entity has been archived, it will not be displayed under **Relationships** in the entity's sidebar.

If the entity itself has been archived, you will see an "Archived" flag appear next to its name:

<div align="left"><figure><img src="/files/TlC8aX04XxPvJaG37v47" alt="An archived entity has an &#x22;archived&#x22; label next to its name."><figcaption></figcaption></figure></div>

### Entity configuration

While configuring an entity, you cannot add an archived team as an owner. You cannot add archived entities as dependencies or as parent or child entities.

### The discovered entities list

Cortex will tag detected changes to signify whether an entity or repository has been archived. Learn more in [Viewing discovered entities](/ingesting-data-into-cortex/entities-overview/entities/discovery-audit).


# Relationship graph

In Cortex, use the relationship graph to better understand:

* **Dependencies**
  * Visualize how entities relate to one another
    * You can also [sync dependencies](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/dependencies#sync-dependencies) from the Relationship Graph.

      <figure><img src="/files/Y03vx76wyZNoQe26gQi4" alt="Visualize dependencies in the relationship graph."><figcaption></figcaption></figure>
* **Domains**
  * See a hierarchical diagram of your software architecture

    <figure><img src="/files/ay3d7KfnuzKaPb2q2QQV" alt="Visualize domains in the relationship graph."><figcaption></figcaption></figure>
* **Teams**
  * View your company's team structure

    <figure><img src="/files/xMPSfkdszE3SrIxHGm1K" alt="Visualize teams in the relationship graph."><figcaption></figcaption></figure>

## View the relationship graph

You can access the relationship graph from the main nav: Navigate to **Tools > Relationship graphs**. By default, the page displays all entities with dependencies and how they relate to one another.

## Filter the relationship graph

{% hint style="info" %}
If you have more than 500 nodes in the graph, you must select a filter before the graph will display.
{% endhint %}

### Select a relationship type

At the top of the page, choose which relationships you want to view: Dependencies, domains, or teams.

<figure><img src="/files/RWKLnR1flfUqDBqL446c" alt=""><figcaption><p>Select dependencies, domains, or teams.</p></figcaption></figure>

### Filter the graph

You can apply filters to narrow the scope of the graph:

1. Click **Filters** at the top of the page.
2. Apply filters for the following options:
   * Sources
   * Groups
   * Entity types
   * Degrees from selected node

The page will automatically apply your selected filters and reload the visualization.

### Select a display option

At the top of the graph, click **Display options** to select:

* A Scorecard to filter the graph by
* Whether to hide team nodes without children
* Whether to hide archived entities

### View more details on an entity

In the graph, click an entity to open a modal with the ability to:

* Filter by this node
* Go directly to its entity details page
* View a list of its child entities or dependencies

<div align="left"><figure><img src="/files/RFpSWM9lrqwoIYlvTWC1" alt=""><figcaption><p>Click a node to open a modal with more information.</p></figcaption></figure></div>

## Adjust appearance settings

You must have the `Configure settings` permission.

Under [**Settings > Relationship graph**](https://app.getcortexapp.com/admin/settings/appearance/relationship-graph), you can select whether to display dependencies, domains, or teams by default when you first open the relationship graph.


# Using On-call Assistant for incidents

Cortex’s On-call Assistant leverages the [PagerDuty integration](/ingesting-data-into-cortex/integrations/pagerduty) to automatically surface the most vital information about entity health and metadata when an incident is triggered. On-call Assistant notifies the user(s) responsible for an incident via Slack, including information about the affected entity, recent deployments, ownership, and links to get more details, including dependencies, runbooks, and logs.

On-call Assistant helps users respond to incidents in real time, simplifying the incident response process and helping to reduce MTTR. It can also drive adoption and engagement through links to the catalogs and Scorecards.

## How On-call Assistant works

### Notifications

When an incident is triggered in PagerDuty, On-call Assistant will notify relevant users via [Slack](/ingesting-data-into-cortex/integrations/slack). This alert will include information about the affected entity, deploy details, and ownership information so an on-call team member can reach out to other relevant parties about the incident.

![On-call assistant notifies users via Slack.](/files/Y6kiXAoQphrCjOcPyHIW)

Developers can access entity information that is already in Cortex directly from the Slack notification to quickly resolve issues. On-call Assistant provides a direct link to view the alert in PagerDuty, so you can also quickly access the incident from its source.

#### View runbooks and other links

![The notification includes runbooks and other links.](/files/Y9t5j8pSNDwqleyvPg4l)

#### View dependencies

![The notification includes dependencies.](/files/9NpkbWQgzLufuFtJBISF)

## Enabling On-call Assistant

### Prerequisites

* You must have the [PagerDuty integration](/ingesting-data-into-cortex/integrations/pagerduty) configured.
* You must create an [API key](https://support.pagerduty.com/main/docs/api-access-keys#rest-api-keys) in PagerDuty with the `Write` permission.
  * If you create an API key with `Read-only` permissions, you will also need to configure a webhook to get the On-call Assistant working.

### Enable On-call Assistant in Cortex

To enable, navigate to [**Settings > PagerDuty**](https://app.getcortexapp.com/admin/settings/pagerduty) and toggle on **Enable On-call Assistant**.

<figure><img src="/files/bAyiB4wnFcVdYvDuoDbN" alt=""><figcaption></figcaption></figure>

If you added PagerDuty API key with `Write` permissions, enabling the On-Call Assistant will create a webhook subscription in PagerDuty, allowing Cortex to receive events when incidents are triggered, escalated, or unacknowledged.

#### Configure a webhook for read-only API keys

If you added PagerDuty API key with `Read-only` permissions, you must also configure a webhook subscription.

1. In Cortex, on the [PagerDuty settings page](https://app.getcortexapp.com/admin/settings/pagerduty), click **Configure webhook**.\
   ![](/files/VdhBOz3l2G3p3Seuz1LO)
2. Copy the webhook URL. You will need this in the next steps.
3. In PagerDuty, add a new webhook.
   * Paste the Cortex webhook URL into the **Webhook URL** field.
   * Choose `Account` for **scope type**.
   * Select only the following in Event Subscription:
     * `incident.escalated`
     * `incident.reopened`
     * `incident.triggered`
     * `incident.unacknowledged`
4. A secret will be generated. Copy the secret. You will need it in the next step.
5. Navigate back to the browser window where your Cortex instance is open. In the Webhook configuration **Secret** field, enter the secret that you generated in PagerDuty.\
   ![](/files/QWvMm7TvgjOvTsB1eU2y)
6. Click **Save** at the bottom of the side panel.


# Managing Terraform infra in Cortex

Cortex Workflows can trigger Terraform execution to manage your cloud infrastructure, such as provisioning new services, databases, buckets, or networking primitives.

[Terraform](https://developer.hashicorp.com/terraform/intro) is an infrastructure-as-code tool that lets you provision, manage, and update infrastructure. Terraform can help you manage databases, s3 buckets, clusters, and every other component that comprises your infra. Terraform’s ability to manage resources comes from **providers**, which are plugins that enable interaction with cloud providers, SaaS providers, and other APIs. Providers allow you to define as code what a resource looks like.

The instructions on this page apply to [Terraform Cloud](https://developer.hashicorp.com/terraform/tutorials/cloud-get-started/cloud-sign-up), the web-based interface for Terraform.

{% hint style="info" %}
Cortex integrates with Terraform in two different ways, depending on whether you want to manage Cortex resources using Terraform or use Cortex to drive Terraform runs for your infrastructure.

To learn about managing Cortex resources using Terraform, see [Manage entities using Cortex Terraform Provider](/ingesting-data-into-cortex/entities-overview/entities/terraform/terraform-provider).
{% endhint %}

## How to manage Terraform infrastructure in Cortex

{% hint style="success" %}
See end-to-end examples for [using a Workflow to provision an EC2 instance with Terraform](https://github.com/cortexapps/hippocampus/blob/master/ingesting-data-into-cortex/entities/broken-reference/README.md), [using a Workflow to update the EC2 instance](https://github.com/cortexapps/hippocampus/blob/master/ingesting-data-into-cortex/entities/broken-reference/README.md), and [using a Workflow to destroy a resource](https://github.com/cortexapps/hippocampus/blob/master/ingesting-data-into-cortex/entities/broken-reference/README.md).
{% endhint %}

### Prerequisite

Expand the tile below for instructions on provisioning a new instance.

<details>

<summary>Provision a new instance and update the instance name</summary>

* Provision a new instance
  * Terraform will automatically provide you with a starter workspace when you begin — our example workspace is named **"tfc-guide-example"**.

<div align="left"><img src="/files/AejgHmD0hDWvaVHLkq2k" alt="Our example workspace is named &#x22;tfc-guide-example&#x22;" width="563"></div>

* Update the instance name in the Terraform `variables.tf` file.
  * All Terraform modules come with a file called `variables.tf`. As part of the Terraform script, we can enter variables for a given set, like region or instance type. In the example screen shot below, the variable name is "My Other Great Instance".

<div align="left"><img src="/files/ZzSxOI2nhsImuwyb8Bbj" alt="The variable instance name is &#x22;My other great instance.&#x22;" width="375"></div>

* Note: Terraform modules also come with a `main.tf` file, which contains instructions and information about the action. In our example, the `main.tf` file describes the instance that we’re going to create through Terraform.

![Example of the main.tf file](/files/SwpnYlI1U7NuusK2N33q)

{% hint style="info" %}
Terraform stores a “state” about your infrastructure and configuration when it’s deployed. State maps resources to this configuration, and will update any time variables or properties are changed.
{% endhint %}

</details>

### Step 1: Confirm your instance name update in Terraform

In Terraform Cloud, navigate to the **Run** page. Verify that the changes you made to the instance name in `variables.tf` have applied.

<div align="left"><img src="/files/vlr2ud7RS3Aen8dWGo4Y" alt="In Terraform, verify that your changes have applied." width="563"></div>

In Terraform, there are two primary commands: `plan` and `apply`.

* The `plan` command creates a plan and preview of the changes that will be made to your infrastructure. During the plan stage, Terraform assesses the `main.tf` file with variables and compares it against the state. If there are differences, Terraform prompts you to approve and apply the change.
* When you navigate to the run that was triggered by updating `variables.tf`, you can see that the plan was automatically conducted. In this case, the plan was to create an instance with the name provided earlier. Verify that the run displays a "Plan finished" message.

<div align="left"><img src="/files/lvqVS2Y1m6xSKgPTAYR2" alt="Terraform displays a &#x22;Plan finished&#x22; message." width="563"></div>

In AWS, you can confirm that the instance exists and that the Terraform action was successful:

![AWS shows that the instance exists.](/files/tnBnVbv1bpFW2tOA7ORw)

{% hint style="info" %}
In this example, we made direct modifications to the main branch, but typically, you will edit a separate branch and create a pull request. This approach will run a plan in Terraform, but will not automatically apply changes.
{% endhint %}

### Step 2: Add the Terraform template in Cortex

Cortex not only integrates with Terraform, but can enhance your use of it. Once the integration is set up, you’ll use a [Scaffolder step in a Workflow](/streamline/workflows#scaffolder) to interact with Terraform.

You must have the `Configure Scaffolder templates` permission.

{% hint style="info" %}
When using the Scaffolder, it's best to edit a secondary branch and create a pull request — the Scaffolder will actually create the pull request for you, which someone else can approve to apply the changes.
{% endhint %}

1. Create a [Cookiecutter](https://www.cookiecutter.io/) JSON file that is equivalent to your Terraform module.
   * In this file, we defined the region and instance name. You’ll then update the fields in the `variables.tf` file so it knows to pull information from the Cookiecutter JSON.\
     ![](/files/yq0nCQXZqRi44UCLroZT)
2. [Register your template](/streamline/workflows/scaffolder#step-2-add-the-template-to-cortex) in Cortex.
3. After you have added the template to Cortex, you can [create a Workflow](/streamline/workflows) that includes a [Scaffolder](/streamline/workflows#scaffolder) block using the template.
4. Run the Workflow. When you run it, Cortex will automatically open a pull request against the selected repository.

#### Verify that the process worked

<details>

<summary>Verify the process</summary>

To verify that the process worked, open Terraform Cloud and navigate to **Runs**.

Any runs that originate from Cortex will have `[Cortex Scaffolder]` at the start of their name. Click into one of these runs to see its status and how many changes were proposed.

<div align="left"><img src="/files/Lf9dAXnx0JrE6JaT6gr6" alt="A Cortex Scaffolder run shows as planned and finished in Terraform." width="563"></div>

</details>

## Execute a run via a Workflow

Terraform Cloud also has an API that can be used to make updates without following the pull request workflow. You can use a [Workflow](/streamline/workflows) in Cortex to execute a run through the API. If a run is set to automatically apply, then Cortex will handle the rest of the process.

1. [Create a Workflow](/streamline/workflows) in Cortex.
2. Add a [user input](/streamline/workflows#user-input) block.
   1. Define inputs for `Instance name`, `Region`, and `Instance type`.
3. Add an [HTTP request](/streamline/workflows#http-request) block. Configure the following fields:
   1. **HTTP method**: Select `POST`.
   2. **URL**: Enter the URL for the Terraform API you want to call.
   3. **Headers**: Add `Authorization: Bearer {{token}}` and `Content-type: application/(name)`.
   4. **Payload**: Build the payload by referencing the outputs of the "User input" block, e.g., `{{actions.input.outputs.instance-name}}`
4. Save the Workflow. After saving, click **Run** at the top of the Workflow to run it.

When the Workflow is run in Cortex, it will override data in the `variables.tf` file with information that was entered in the fields.

#### Verify the run

<details>

<summary>Verify that the action was successful</summary>

In Terraform Cloud, you can verify that the action was successful and the run was queued. Runs triggered by actions are named "Triggered via API."

<div align="left"><img src="/files/y9nEFfB1mPitCsrkXltj" alt="The run in Terraform is labeled &#x22;Triggered via API.&#x22;" width="563"></div>

Once the run has been applied, you can also verify it in AWS. In the example screen shot below, the instance name has been changed:

![The instance is listed in AWS.](/files/V2UO1vlYEs0cvITqFe2j)

</details>

## Terraform Workflow examples

See guides on creating the following Workflows: [Provision EC2 instance with Terraform](/guides/production-readiness/terraform/provision), [Update EC2 instance](/guides/production-readiness/terraform/update), and [Terraform destroy](/guides/production-readiness/terraform/destroy).


# Manage entities using Cortex Terraform Provider

The [Cortex Terraform Provider](https://github.com/cortexapps/terraform-provider-cortex) acts as a bridge between Terraform and the Cortex platform, allowing you to manage and provision Cortex resources (such as [Scorecards](/standardize/scorecards), [integrations](/ingesting-data-into-cortex/integrations), and [entities](/ingesting-data-into-cortex/entities-overview/entities)) using Terraform’s infrastructure-as-code approach. The provider is a wrapper around the public Cortex API and is maintained by the Cortex team, with shared ownership and ongoing support for customers who use it.

{% hint style="info" %}
Cortex integrates with Terraform in two different ways, depending on whether you want to manage Cortex resources using Terraform, or use Cortex to drive Terraform runs for your infrastructure.

To learn about using Cortex to drive Terraform runs, see [Managing Terraform infra in Cortex](/ingesting-data-into-cortex/entities-overview/entities/terraform).
{% endhint %}

### Managing the catalog as code

Many Cortex customers manage their entire service catalog and engineering standards as code using the Cortex Terraform Provider.

Expand the tiles below for examples on how to handle different use cases with this approach.

<details>

<summary>Service catalog as code</summary>

**Goal:** Any time a new microservice or app is created (via a Terraform module, template repo, or platform workflow), it’s automatically added to the Cortex catalog with the right metadata and ownership.\
\
**How to do it:**

* Use the `cortex_catalog_entity` resource to create and update services, libraries, or other catalog entities from Terraform.
* Attach extra metadata with `cortex_catalog_entity_custom_data` – e.g. `tier`, `business_unit`, `cost_center`, “is\_internally\_facing”, etc.
* Optionally define departments (e.g. “Payments”, “Growth”) with `cortex_department`, and link services/teams to those for reporting and ownership.

</details>

<details>

<summary>Scorecards and standards as code</summary>

**Goal**: Treat operational standards (SRE, security, compliance, production-readiness gates) as code that lives next to infrastructure, reviewed via PRs and rolled out safely.\
\
How to do it:

* Define scorecards via the `cortex_scorecard` resource. It supports:
  * a ladder (levels with names, colors, rank)
  * rules (expressions, titles, weights, optional failure messages)
  * an evaluation window (how often to evaluate, min every 4 hours)
  * a filter to target specific entity types or groups
* Use `cortex_resource_definition` to standardize external signals that Scorecards rely on (e.g. “has SLO in Datadog”, “has PagerDuty service”, “has runbook link”).
* Manage changes to standards through Git review: PRs update the Terraform code, then Terraform updates the Cortex Scorecards and resources.

</details>

<details>

<summary>API contracts and org model as code</summary>

**Goal**: Ensure that API documentation and org metadata are always in sync, accurate, and consistent across environments.\
\
How to do it:

* Use `cortex_catalog_entity_openapi` to attach OpenAPI specs (YAML/JSON) to catalog entities in Cortex, keyed by the entity’s tag/ID.
* Keep department and ownership structure in Terraform via `cortex_department` and catalog entity custom data (e.g., `department`, `team`, `criticality`).
* When infrastructure changes (e.g., new API version, team moves between org units), updating Terraform automatically pushes the new OpenAPI spec + org metadata into Cortex.

</details>

## Install the Terraform Provider for Cortex

For installation instructions, see the [repository's README in GitHub](https://github.com/cortexapps/terraform-provider-cortex).

### Examples

See [the repository for examples](https://github.com/cortexapps/terraform-provider-cortex/tree/main/examples).


# Managing Catalogs

A catalog is a defined selection of [entities](/ingesting-data-into-cortex/entities-overview/entities). You can use catalogs to track and store information about all of the components that make up your infrastructure. This includes everything from services and domains to AWS S3 buckets and RDS, Google Cloud resources, or Azure Resources.

While entities are [defined by YAML files](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file), catalogs themselves are not defined by a YAML file and must be created in the Cortex UI. Think of catalogs as a folder containing a collection of entities, with each entity defined by its own YAML file. An entity can belong to multiple catalogs, so you can also think of a catalog as a filter that defines which entity types to group together.

In the example screen shot below, the Services page contains a list of all entities that belong to the Service catalog:

<figure><img src="/files/vKTTLdM72FuqiOz2oYlA" alt="The services catalog displays a list of services."><figcaption></figcaption></figure>

{% hint style="success" %}
Want to learn more? Check out the [Cortex Academy course on Catalogs](https://academy.cortex.io/courses/introduction-to-catalogs), available to all Cortex customers and POVs.
{% endhint %}

## Catalogs and entities overview video

In the video below, see an overview of how Cortex helps you build and catalog your engineering operations assets helping to improve visibility, adoption, and productivity:

{% embed url="<https://www.youtube.com/watch?v=A5w6ebxGbeg>" %}

## Default catalogs

By default, Cortex comes with four built-in catalogs:

* **Services** contains all [service entities](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services).
* **Infrastructure** contains all entities representing your infrastructure assets.
  * Cortex pulls in resources directly from [AWS](/ingesting-data-into-cortex/integrations/aws), [Azure Resources](/ingesting-data-into-cortex/integrations/azureresources), or [Google Cloud](/ingesting-data-into-cortex/integrations/google), as their corresponding types out of the box. These resources are automatically added to the Infrastructure catalog.
* **Domains** contains all [domain entities](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/domains) and their children entities (regardless of entity type), and displays them in a hierarchical view.
* **Teams** contains all [team entities](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams) and displays them in a hierarchical view alongside a leaderboard based on Scorecards.

You can choose to rename these catalogs to fit your own taxonomy, but note that the custom names of these default catalogs will not override the references to their default names throughout the app. Instead, you could choose to create additional custom catalogs.

### Custom catalogs

To customize your Cortex instance to your organization's needs, you can also define custom catalogs in Cortex to represent your infrastructure. See [Create custom catalogs](#create-custom-catalogs) below.

### Catalog types

There are two types of catalogs:

* **Entity type catalogs**
  * Define entity inclusion criteria through filters for entity type, tags, or groups.
  * For example, the built-in "service" catalog is configured to include entities of type `service`.
* **Relationship type catalogs**
  * This type enables grouping of entities based on a specific [entity relationship type](/ingesting-data-into-cortex/entities-overview/entities/defining-relationship-types). These catalogs support visualizing hierarchical relationships. They support the ability to have different entity types relate to one another.
  * For example, the built-in "domain" catalog includes entities associated with each other via parent/child domain relationship. This catalog displays all entities that are a part of the domain hierarchy, including entity types that are not domains.

## View catalogs

Click **Catalogs** from the main nav to view your list of catalogs. You must have the `View catalogs` permission.

<figure><img src="/files/gxFvCaXMlMJ8UB2klH0S" alt=""><figcaption><p>Click "Catalogs" in the main nav to view catalogs.</p></figcaption></figure>

### View a catalog's entity list

When you click into a catalog, you can view all of the entities that belong to that catalog:

<figure><img src="/files/gqrxaK9G1UZ4y8oyDUul" alt="When you click into the Services catalog, you see a list of all service entities."><figcaption></figcaption></figure>

#### Display options for entity relationship catalogs

If a catalog can be configured with a hierarchy (such as domains, teams, or custom catalogs based on [relationship types](/ingesting-data-into-cortex/entities-overview/entities/defining-relationship-types)), you can choose what is displayed in the list view:

1. At the top of the list, click **Display**.
2. Configure the display options:
   * To include the hierarchy in the list view, enable the toggle next to **Display hierarchy**.
   * To include entities that are not connected to any other entities, enable the toggle next to **Show empty**.
   * To include archived entities in the list view, enable the toggle next to **Show archived**.\
     ![](/files/Zf5CIve6YccymS2xVFAn)
3. Click **Done**.

### The "All entities" page

#### All entities

The "All entities" page includes entities across all catalogs and entities of all types, whether the entity is one of the [default types](/ingesting-data-into-cortex/entities-overview/entities#default-entity-types) or whether it is a [custom entity type](/ingesting-data-into-cortex/entities-overview/entities#custom-entity-types). To access this page, go to **Catalogs > All Entities**.

#### All entity types

To view all entity types, go to **Catalogs > All Entities** then click the [**Entity types** tab](https://app.getcortexapp.com/admin/entities?activeTab=EntityTypes).

Learn more about entities in [Managing Entities](/ingesting-data-into-cortex/entities-overview/entities).

## Manage all catalogs

On the [**All catalogs** page](https://app.getcortexapp.com/admin/catalogs), you’ll find all pre-defined and custom catalogs in Cortex.

This page will reflect the same list of catalogs you find in the **Catalogs dropdown menu** in the main nav.

![The "All catalogs" page displays all catalogs in the workspace.](/files/LlVzuAvMey3UqK7vCeH8)

Just like "All entities", "All catalogs" includes a search bar and a sort function, as well as a toggle for displaying or hiding Drafts.

From this page, you can create new catalogs and edit existing ones.

### Create custom catalogs

You can create catalogs in the Cortex UI. For each catalog, you set the criteria that determines which entities belong to that catalog. In addition, you can define custom entity types to categorize the entities that live in your catalogs.

Because catalogs are not defined by a YAML file, it is not possible to create them via a GitOps workflow.

To create, edit, and delete catalogs, you must have the `Edit catalogs` permission.

To create a new catalog:

1. At the top of the "All catalogs" page, click **Create catalog**.
2. Configure the "Create catalog" form:
   * **Name**: Enter a name for the catalog.
   * **Description**: Optionally, enter a description of the catalog.
   * **Display icon**: an icon to appear alongside the catalog throughout the app.
   * **URL**: Enter a unique URL slug.
     * By default, the URL slug will be generated based on the catalog’s name, but you can use the URL field to create a custom slug.
   * **Catalog filter**: In this section, you can define the entities that are included in your catalog. All entities that match the criteria defined in this section will be automatically included in the catalog. You can use one filter to define a catalog page — choose an entity type or a relationship type.
     * **Option 1: Entity Type**: Catalogs can include a combination of any entity types, or can include just one type.
       * Choose whether to include or exclude the entity types you select.
       * Optionally, under "Advanced options," enter a specific CQL expression to fine-tune your catalog based on specific criteria.
     * **Option 2: Relationship Type**: Catalogs can include one relationship type.\\

       <div align="left"><figure><img src="/files/MPSRcQGueeqoiWRxT2oN" alt="" width="375"><figcaption></figcaption></figure></div>
   * **Save as draft**: Choose whether to save the catalog as a draft or publish it. Only admins and managers have the ability to view drafts.
3. Click **Create**.

Once the catalog is created, you’ll find it under **Catalogs > All catalogs**, automatically populated with all entities that apply based on the entity types you've created. Catalogs with a relationship type filter can be displayed as a hierarchy.

### Edit catalogs

You can edit a catalog's name, description, URL, display icon, and catalog filter type.

To edit a catalog:

1. In Cortex, go to **Catalogs > All catalogs**. Click into the catalog you want to edit, then click **Edit catalog** at the top of the page.
   * This will bring you back to the catalog creation page, with all the details from your last save.
2. Make any changes necessary to the catalog.
3. At the bottom of the page, click **Save catalog**.

#### Track catalog changes

You can use the [audit log](/configure/settings/audit-logs) to track changes made to any of your catalogs. Catalog updates will be listed as `CATALOG` in the **Type** column, and the updated catalog will be listed under the **Entity** column.

The **Action** column will indicate whether a catalog was created, deleted, or updated.

### Adding entities to catalogs

After an entity is imported or created, it will automatically belong to a catalog based on the entity type criteria set for each catalog. When you [create a custom catalog](#create-catalogs), you can set the entity type criteria.

For the default catalogs, the entity type criteria is set by default:

* The **Services** catalog contains `service` entity types
* The **Domains** catalog contains `domain` entity types
* The **Teams** catalog contains `team` entity types
* The **Infrastructure** catalog contains any entities that are *not* the types `service`, `domain`, or `team`.
  * By default, any [custom entity types](#create-entity-types) you create will belong to the Infrastructure catalog. If you do not want the entity type to belong to this catalog, you can add the entity type to a different catalog.

### Configure catalog display

You must have the `Configure appearance settings` permission to configure the catalog display.

By default, catalogs will appear in alphabetical order, but you can manually adjust the order that the catalogs appear in the main nav.

Navigate to [**Settings > Workspace > Main sidebar**](https://app.getcortexapp.com/admin/settings/appearance/main-sidebar) to drag and drop catalogs into your preferred order:

<figure><img src="/files/KEJOHVK09DzjdkcftIto" alt=""><figcaption><p>In the sidebar appearance settings, drag and drop catalogs to reorder them.</p></figcaption></figure>


# Integrations

**Seamlessly Connect Your Entire Stack**

Cortex supports a broad set of [third-party](#third-party-integrations), [internally hosted](#internally-hosted-integrations), and [custom webhook](#custom-webhook-integration) integrations designed to meet your engineering organization where it already works. Whether you're connecting source control, CI/CD pipelines, incident management tools, or cloud infrastructure providers, Cortex fits into your existing workflows without significant setup overhead or custom development.

**Key Benefits**

* **Centralized data synchronization**. Aggregate data from across your toolchain into a single, unified view. Eliminate the need for manual data collection and reduce the risk of fragmented or inconsistent reporting.
* **Flexibility at scale**. Cortex supports organizations of all sizes, offering both out-of-the-box integrations and extensible configurations for teams with more specialized tooling requirements.
* **Minimal operational overhead**. Once configured, integrations run continuously in the background, keeping your platform data fresh and reliable without ongoing maintenance from your team.
* **Secure and compliant by design**. All integration connections are established using industry-standard authentication protocols, ensuring your data is transmitted and stored in accordance with your organization's security requirements.

<div align="left" data-with-frame="true"><figure><img src="/files/41GhSHvaQzG0ST1reCOc" alt=""><figcaption></figcaption></figure></div>

Users can view the Integrations page to check which integrations are configured and monitor their health status. To install, uninstall, or modify integrations, users must have the `Configure Integrations` permission.

{% hint style="info" %}
Integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

## Third-party integrations

Cortex connects to each tool via its official API, pulling live data directly from your systems. When viewing an entity, the information displayed reflects the current state of your tools—no manual syncing or stale data to manage.

Cortex integrates with tools across the core domains of engineering operations, including:

### Essentials

<details>

<summary>Version control</summary>

* [Azure DevOps](/ingesting-data-into-cortex/integrations/azuredevops)
* [Bitbucket](/ingesting-data-into-cortex/integrations/bitbucket)
* [GitHub](/ingesting-data-into-cortex/integrations/github)
* [GitLab](/ingesting-data-into-cortex/integrations/gitlab)

</details>

<details>

<summary>Team/Ownership</summary>

* [Azure DevOps](/ingesting-data-into-cortex/integrations/azuredevops)
* [BambooHR](/ingesting-data-into-cortex/integrations/bamboohr)
* [Entra ID (formerly Azure Active Directory)](/ingesting-data-into-cortex/integrations/entraid)
* [GitHub](/ingesting-data-into-cortex/integrations/github)
* [GitLab](/ingesting-data-into-cortex/integrations/gitlab)
* [Google](/ingesting-data-into-cortex/integrations/google)
* [Okta](/ingesting-data-into-cortex/integrations/okta)
* [Opsgenie](/ingesting-data-into-cortex/integrations/opsgenie)
* [ServiceNow](/ingesting-data-into-cortex/integrations/servicenow)
* [Workday](/ingesting-data-into-cortex/integrations/workday)

</details>

<details>

<summary>On-call</summary>

* [PagerDuty](/ingesting-data-into-cortex/integrations/pagerduty)
* [Opsgenie](/ingesting-data-into-cortex/integrations/opsgenie)
* [Splunk On-Call (formerly VictorOps)](/ingesting-data-into-cortex/integrations/splunk-oncall)
* [xMatters](/ingesting-data-into-cortex/integrations/xmatters)

</details>

<details>

<summary>Project management</summary>

* [Azure DevOps](/ingesting-data-into-cortex/integrations/azuredevops)
* [ClickUp](/ingesting-data-into-cortex/integrations/clickup)
* [GitHub](/ingesting-data-into-cortex/integrations/github)
* [GitLab](/ingesting-data-into-cortex/integrations/gitlab)
* [Jira](/ingesting-data-into-cortex/integrations/jira)

</details>

<details>

<summary>Communication</summary>

* [Slack](/ingesting-data-into-cortex/integrations/slack)
* [Microsoft Teams](/ingesting-data-into-cortex/integrations/microsoftteams)

</details>

<details>

<summary>Code quality</summary>

* [Codecov](/ingesting-data-into-cortex/integrations/codecov)
* [SonarQube](/ingesting-data-into-cortex/integrations/sonarqube)

</details>

### Extended

<details>

<summary>CI/CD</summary>

* [ArgoCD](/ingesting-data-into-cortex/integrations/argocd)
* [Azure DevOps](/ingesting-data-into-cortex/integrations/azuredevops)
* [Buildkite](/ingesting-data-into-cortex/integrations/buildkite)
* [CircleCI](/ingesting-data-into-cortex/integrations/circleci)
* [GitHub](/ingesting-data-into-cortex/integrations/github)
* [Jenkins](/ingesting-data-into-cortex/integrations/jenkins)

You can also use Cortex's [deploys API](/api/readme/deploys) to send deployment data from other services to Cortex.

</details>

<details>

<summary>Cloud</summary>

* [AWS](/ingesting-data-into-cortex/integrations/aws)
* [Azure Resources](/ingesting-data-into-cortex/integrations/azureresources)
* [Google](/ingesting-data-into-cortex/integrations/google)
* [Kubernetes](/ingesting-data-into-cortex/integrations/kubernetes)
* [Syntasso Kratix Enterprise (SKE)](/ingesting-data-into-cortex/integrations/syntasso)

</details>

<details>

<summary>Error tracking</summary>

* [BugSnag](/ingesting-data-into-cortex/integrations/bugsnag)
* [Rollbar](/ingesting-data-into-cortex/integrations/rollbar)
* [Sentry](/ingesting-data-into-cortex/integrations/sentry)

</details>

<details>

<summary>Feature flags</summary>

* [LaunchDarkly](/ingesting-data-into-cortex/integrations/launchdarkly)

</details>

<details>

<summary>Incidents</summary>

* [FireHydrant](/ingesting-data-into-cortex/integrations/firehydrant)
* [Incident.io](/ingesting-data-into-cortex/integrations/incidentio)
* [PagerDuty](/ingesting-data-into-cortex/integrations/pagerduty)
* [Rootly](/ingesting-data-into-cortex/integrations/rootly)

</details>

<details>

<summary>Observability</summary>

* [Coralogix](/ingesting-data-into-cortex/integrations/coralogix)
* [Datadog](/ingesting-data-into-cortex/integrations/datadog)
* [Dynatrace](/ingesting-data-into-cortex/integrations/dynatrace)
* [Google Observability Cloud](/ingesting-data-into-cortex/integrations/google)
* [Instana](/ingesting-data-into-cortex/integrations/instana)
* [New Relic](/ingesting-data-into-cortex/integrations/newrelic)
* [Prometheus](/ingesting-data-into-cortex/integrations/prometheus)
* [ServiceNow Cloud Observability (formerly Lightstep)](/ingesting-data-into-cortex/integrations/lightstep)
* [Splunk Observability Cloud (formerly SignalFX)](/ingesting-data-into-cortex/integrations/splunk-observability)
* [Sumo Logic](/ingesting-data-into-cortex/integrations/sumologic)

</details>

<details>

<summary>Security</summary>

* [Apiiro](/ingesting-data-into-cortex/integrations/apiiro)
* [Checkmarx](/ingesting-data-into-cortex/integrations/checkmarx)
* [GitHub](/ingesting-data-into-cortex/integrations/github)
* [GitLab](/ingesting-data-into-cortex/integrations/gitlab)
* [Mend](/ingesting-data-into-cortex/integrations/mend)
* [Semgrep](/ingesting-data-into-cortex/integrations/semgrep)
* [Snyk](/ingesting-data-into-cortex/integrations/snyk)
* [Veracode](/ingesting-data-into-cortex/integrations/veracode)
* [Wiz](/ingesting-data-into-cortex/integrations/wiz)

</details>

<details>

<summary>ITSM</summary>

* [ServiceNow](/ingesting-data-into-cortex/integrations/servicenow)

</details>

### Configuring third-party integrations

Cortex integrates with a wide range of third-party tools to surface relevant data across your workspace. Users with the `Configure Integrations` permission can install, uninstall, or modify integrations.

1. From the main sidebar, select **Integrations**.
2. Locate the integration you want to set up, then click **Install**. Specific configuration steps and required credentials vary depending on the integration.

### Modifying an existing integration configuration

Users with the `Configure Integrations` permission can install, uninstall, or modify integrations.

In Cortex, you can modify an existing integration configuration directly, without needing to delete and re-add it. This applies to all editable fields, including credentials, and is supported for both single and multi-configuration integrations.

{% hint style="info" %}
**The following third-party configurations cannot be modified**

OAuth-based configurations cannot be directly modified. To make changes, you'll need to delete and re-install the integration, since setup requires a third-party redirect. This applies to: Bitbucket Atlassian App, GitHub App, Kubernetes (which uses its own unique flow), Microsoft Teams, and Slack.&#x20;

Additionally, configuration management isn't available for ArgoCD, Humanitec, and Syntasso.
{% endhint %}

1. From the main sidebar, select **Integrations**.
2. Locate the integration you want to edit, then click **Settings**. \
   The integration page is displayed.
3. Locate the configuration you want to edit, then click the **pencil icon**.
4. Make your edits, then click **Save**.

## Internally hosted integrations

If your tooling is hosted within your own infrastructure rather than the cloud, Cortex can still connect to it. Internally hosted integrations allow you to source data from systems running behind your firewall or private network and reflect that data in Cortex, giving you the same visibility and platform functionality without requiring your tools to be publicly accessible.

**Example use case**

If your team runs tools like GitLab, Jenkins, or Jira on private infrastructure rather than in the cloud, or relies on proprietary internal tooling for tracking services, deployments, or ownership, internally hosted integrations allow Cortex to pull in that data without requiring those systems to be publicly accessible.

See [Internally hosted integrations](/ingesting-data-into-cortex/integrations/axon-relay) for more information.

## Custom webhook integrations

Custom webhook integrations allow you to send data to Cortex from virtually any source, including internal tooling or systems that don't have a native Cortex integration. Each webhook generates a unique URL that accepts arbitrary JSON payloads via `POST`—no authentication headers or Cortex entity tags required. This makes custom webhooks a flexible option for teams that need to pipe in data from homegrown tools, scripts, or automated workflows that fall outside Cortex's standard integration offerings.

**Example use case**

If your team uses an internal deployment tool that isn't supported as a native integration, you can configure it to `POST` deployment events directly to your custom webhook URL, making that data available within Cortex without any additional middleware.

See [Custom webhook integrations](/ingesting-data-into-cortex/integrations/webhook) for more information.

## SSO integrations for Cortex workspace access

Single sign-on (SSO) allows users to authenticate with Cortex using the same credentials they already use across your organization's other tools and systems. Rather than managing a separate set of login credentials, users sign in once through your identity provider—such as Okta, Google, or Microsoft Entra ID—and gain access automatically. For organizations with strict security or compliance requirements, SSO also provides centralized control over user access, making it easier to provision and deprovision accounts as team members join or leave.

Cortex supports the following SSO integrations:

* [Microsoft Entra ID](/configure/settings/managing-users/configuring-sso/entraid)
* [Google](/configure/settings/managing-users/configuring-sso/google)
* [Okta](/configure/settings/managing-users/configuring-sso/okta)
* [Other OIDC providers](/configure/settings/managing-users/configuring-sso/oidc)

## SCIM integrations for provisioning users

System for Cross-domain Identity Management (SCIM) is an open standard protocol that automates the exchange of user identity information between an identity provider (IdP)—such as Microsoft Entra ID or Okta—and a target application like Cortex. It defines a standard schema and REST API for creating, updating, and deprovisioning user accounts, eliminating the need for manual account management.

Cortex supports the following SCIM integrations:

* [Microsoft Entra ID](/configure/settings/managing-users/provisioning-users-with-scim/entraid-scim)
* [Okta](/configure/settings/managing-users/provisioning-users-with-scim/okta-scim)

See [Provisioning users with SCIM](/configure/settings/managing-users/provisioning-users-with-scim) for more information.

## Integration rate limiting

Cortex has built a distributed self-throttling system to ensure that certain functionality, such as CQL evaluations or background syncs to pull data from integrations, are not going over the rate limit thresholds for specific vendors. It handles different rate limit thresholds for different APIs within the same integration, which is common for git APIs such as Bitbucket.

The system is designed to proactively throttle before hitting a 429 from the vendor, and it works regardless of how many evaluators are trying to access that integration. Note that this system does not track other requests with the same token or undocumented limits set by vendors.

## Troubleshooting with integration logs

{% hint style="info" %}
This feature is available in Cortex cloud.
{% endhint %}

While viewing an integration's settings page, click the **Logs** tab to view error logs from the last 7 days. You can filter the logs list by configuration and by operation (for example, you could filter to view errors surfaced only via Scorecards).

<div align="left" data-with-frame="true"><figure><img src="/files/HIwqrjNekko0ilzNA66d" alt="Click the Logs tab on an integration to view integration logs and errors."><figcaption></figcaption></figure></div>

Click into a log to get more information, including time stamp, status code, full error, and request path.


# Internally hosted integrations

Cortex Axon is a framework that can be used to build jobs that run in your environment and securely send data to Cortex. It includes:

* **Custom handlers**: It makes it easy to write code against the Cortex API that can send data to Cortex either on a regular interval, a cron schedule, or after processing a webhook.
  * See the [Cortex Axon README](https://github.com/cortexapps/axon) for more information.
* **Internally-hosted integration support**: Using Axon Relay, it can provide a virtual connection between your network and Cortex. Use it to allow Cortex to access internally-hosted integrations for [Bitbucket](/ingesting-data-into-cortex/integrations/bitbucket), [GitHub](/ingesting-data-into-cortex/integrations/github), [GitLab](/ingesting-data-into-cortex/integrations/gitlab), [Jira](/ingesting-data-into-cortex/integrations/jira), [Prometheus](/ingesting-data-into-cortex/integrations/prometheus), and [SonarQube](/ingesting-data-into-cortex/integrations/sonarqube). You can also use Axon Relay to [call internal service endpoints via a Workflow](https://github.com/cortexapps/hippocampus/blob/master/ingesting-data-into-cortex/integrations/broken-reference/README.md) in Cortex.
  * This documentation page walks you through configuring internal integrations with Axon Relay.

### How it works

<figure><img src="/files/nCtdduo63V1wd3NvwiKo" alt="Network diagram showing how Cortex Axon works."><figcaption></figcaption></figure>

Cortex Axon uses an open-source project published by Snyk called [Snyk Broker](https://docs.snyk.io/implementation-and-setup/enterprise-setup/snyk-broker). Snyk Broker uses WebSockets to create a secure tunnel between the internal network and cloud-hosted Cortex. HTTP requests are redirected through this WebSocket channel to the Axon agent. You do not need to open inbound firewall ports, as the tunnel is initiated from the internal network.

When deploying Axon, you provide your API tokens or credentials as secrets stored on infrastructure you own, within your network. Axon securely holds these credentials and uses them to proxy requests to third-party integrations. Your sensitive information stays inside your virtual private cloud (VPC) and is never exposed to Cortex cloud services.

This is what the process looks like:

1. On the Cortex side, you register the integration, using an alias name you provide.
2. The Cortex Axon Docker container is started with your Cortex API key, the integration type, and the alias.
3. The Cortex Axon agent connects to the Cortex service, authenticates, and registers itself with the integration type and alias name.
4. The agent starts an instance of the snyk-broker client process, and uses configuration details from the `/register` call (the registration in the previous step) to connect to the Cortex backend instance of the snyk-broker server.
5. Once this is established, API calls made on the Cortex side are relayed to the internal network, and the responses are relayed back to the Cortex service.

## How to use Cortex Axon Relay

Axon is composed of an agent which runs in a Docker container ([`cortex-axon-agent`](https://github.com/cortexapps/axon/pkgs/container/cortex-axon-agent)) and integrates with Kubernetes, creating a secure tunnel between the broker and Cortex.

### Prerequisites

Before getting started:

* Create an [API key](/configure/settings/api-keys#managing-api-keys-via-the-cortex-api) in Cortex.
* Create authentication credentials for the integration you're configuring.

### Step 1: Set up the Cortex Axon agent

#### Step 1.1: Configure the Relay in Cortex

{% hint style="info" %}
The Axon integration option can only be configured for [Bitbucket](/ingesting-data-into-cortex/integrations/bitbucket), [GitHub](/ingesting-data-into-cortex/integrations/github), [GitLab](/ingesting-data-into-cortex/integrations/gitlab), [Jira](/ingesting-data-into-cortex/integrations/jira), [Prometheus](/ingesting-data-into-cortex/integrations/prometheus), and [SonarQube](/ingesting-data-into-cortex/integrations/sonarqube).
{% endhint %}

1. In Cortex, click **Integrations**. Search for the integration you are setting up, then click **+Install**.

   <figure><img src="/files/jeUg87xrNIQ3BmARRYlB" alt=""><figcaption></figcaption></figure>
2. For the configuration type, select **Relay**.
3. In the side panel, enter an alias and configure any other necessary fields. At the bottom, click **Save**.

#### Step 1.2: Create a .env file and a docker-compose.yml file

1. Locally on your machine, create a file called `.env`. Inside the file, add contents for the integration you are configuring:

{% tabs %}
{% tab title="Docker Compose" %}
See the [variables for your integration in the README](https://github.com/cortexapps/axon/blob/main/README.relay.md#environment-variables-summary).

For example, for GitLab you would add:

```
CORTEX_API_TOKEN=your_cortex_token
GITLAB_TOKEN=your_gitlab_token
```

{% endtab %}

{% tab title="Kubernetes" %}
To run the agent in Kubernetes, you'll need to create a Deployment that runs the agent with similar configuration [as described above](#how-it-works).

There is a [Helm chart](https://github.com/cortexapps/axon/tree/main/examples/relay/helm-chart) available that can be used as a starting point. Its critical variables are:

```
# Example for github
relay:
  integration: github # can be blank
  subtype:   # optional, can be blank, see table above for options
  alias: alias for configuration from Cortex
  env:
    GITHUB: "https://github.com"
    GITHUB_API: "https://api.github.com"
    GITHUB_GRAPHQL_API: "https://api.github.com/graphql"
  verbose: false # set to true to enable verbose logging
```

If you have a proxy setup you can add values such as:

```
proxy:
  server:  http://proxy.example.com:8080
  noProxy: proxy.example.com # note localhost is added automatically
  certSecretName: my-proxy-ca-pem # name of the secret containing a .pem file with the CA certificate
```

{% endtab %}
{% endtabs %}

2. Locally on your machine, create a file called `docker-compose.yml`. Inside the file, add contents for the integration you are configuring:

{% tabs %}
{% tab title="GitHub" %}
**GitHub**:

```
services:
  axon:
    image: ghcr.io/cortexapps/cortex-axon-agent:latest
    env_file: .env
    env:
      - GITHUB_API=api.github.com
      - GITHUB_GRAPHQL=api.github.com/graphql
    command: [
      "relay",
      "-i", "github",
      "-a", "github-relay", # this is the alias you set up in the Cortex UI

      # if you are using a Github App token, add the following line
      # "-s", "app",
    ]
```

Additional environment variables include: `GITHUB_API=https://api.github.com`, `GITHUB_TOKEN`

**GitHub Hosted**:

```
services:
  axon:
    image: ghcr.io/cortexapps/cortex-axon-agent:latest
    env_file: .env
    env:
      - GITHUB_API=https://github.mycompany.com/api/v3
      - GITHUB_GRAPHQL=https://github.mycompany.com/api/graphql
    command: [
      "relay",
      "-i", "github",
      "-a", "github-relay", # this is the alias you set up in the Cortex UI

      # if you are using a Github App token, add the following line
      # "-s", "app",
    ]
```

Additional environment variables include: `GITHUB=https://github.mycompany.com`, `GITHUB_TOKEN`

**GitHub App**:

```
services:
  axon:
    image: ghcr.io/cortexapps/cortex-axon-agent:latest
    env_file: .env
    env:
      - GITHUB_API=https://api.github.com
      - GITHUB_GRAPHQL=https://api.github.com/graphql
    command: [
      "relay",
      "-i", "github",
      "-a", "github-relay", # this is the alias you set up in the Cortex UI

      # if you are using a Github App token, add the following line
      # "-s", "app",
    ]
```

Additional environment variables include: Arg `-s app`, `GITHUB=https://github.com`, `GITHUB_APP_CLIENT_ID`, `GITHUB_APP_CLIENT_PEM` (either path to PEM or PEM contents), `GITHUB_INSTALLATION_ID`
{% endtab %}

{% tab title="GitLab" %}

```
services:
  axon:
    image: ghcr.io/cortexapps/cortex-axon-agent:latest
    env_file: .env
    env:
      - GITLAB_API=https://gitlab.com
      - GITLAB_TOKEN=<token>
    command: [
      "relay",
      "-i", "gitlab",
      "-a", "gitlab-relay", # this is the alias you set up in the Cortex UI
    ]
```

{% endtab %}

{% tab title="Bitbucket" %}
**Bitbucket Cloud**:

```
    image: ghcr.io/cortexapps/cortex-axon-agent:latest
    env_file: .env
    env:
      - BITBUCKET_API=https://api.bitbucket.org
      - BITBUCKET_TOKEN=<token>
    command: [
      "relay",
      "-i", "bitbucket",
      "-a", "bibucket-relay", # this is the alias you set up in the Cortex UI
    ]
```

**Bitbucket Hosted**:

```
    image: ghcr.io/cortexapps/cortex-axon-agent:latest
    env_file: .env
    env:
      - BITBUCKET_API=https://bitbucket.mycompany.com
      - BITBUCKET_USERNAME=<user>
      - BITBUCKET_PASSWORD=<password>
    command: [
      "relay",
      "-i", "bitbucket",
      "-a", "bibucket-relay", # this is the alias you set up in the Cortex UI
    ]
```

{% endtab %}

{% tab title="Jira" %}
**Jira**:

```
    image: ghcr.io/cortexapps/cortex-axon-agent:latest
    env_file: .env
    env:
      - JIRA_API=https://jira.mycompany.com
      - JIRA_USERNAME:<user>
      - JIRA_TOKEN=<token>
    command: [
      "relay",
      "-i", "jira",
      "-a", "jira-relay", # this is the alias you set up in the Cortex UI
    ]
```

**Jira Bearer/Cloud**:

```
    image: ghcr.io/cortexapps/cortex-axon-agent:latest
    env_file: .env
    env:
      - JIRA_API=https://mycompany.atlassian.com
      - JIRA_TOKEN=<token>
    command: [
      "relay",
      "-i", "jira",
      "-a", "jira-relay", # this is the alias you set up in the Cortex UI
    ]
```

Additional variables include: Arg `-s bearer`
{% endtab %}

{% tab title="SonarQube" %}

```
    image: ghcr.io/cortexapps/cortex-axon-agent:latest
    env_file: .env
    env:
      - SONARQUBE_API=https://sonarqube.mycompany.com
      - SONARQUBE_TOKEN=<token>
    command: [
      "relay",
      "-i", "sonarqube",
      "-a", "sonarqube-relay", # this is the alias you set up in the Cortex UI
    ]
```

{% endtab %}

{% tab title="Prometheus" %}

```
    image: ghcr.io/cortexapps/cortex-axon-agent:latest
    env_file: .env
    env:
      - PROMETHEUS_API=http://mycompany.prometheus.internal
      - PROMETHEUS_USERNAME=<user>
      - PROMETHEUS_PASSWORD=<password>
    command: [
      "relay",
      "-i", "prometheus",
      "-a", "prometheus-relay", # this is the alias you set up in the Cortex UI
    ]
```

{% endtab %}
{% endtabs %}

### Step 2: Run the agent

#### Run the agent in a production environment

In a production environment, you will use a Helm chart, provided by Cortex.

#### Run the agent in a sandbox environment

1. In your CLI, run the command `docker compose up`.
   * You should see the agent start and connect to Cortex.
2. Verify that your agent is working:
   1. In Cortex, go to **Integrations** then navigate to your integration's settings page.
   2. Next to the Relay configuration you set up in the previous steps, click the play icon to test the integration.
      * If you watch the logging output in your CLI, you should see the agent receive the request and forward it to your internal service.
      * The page in Cortex should display a success message.

## Examples

See examples of using Axon with unsupported tools in the [Cortex Axon repository](https://github.com/cortexapps/axon/tree/main/examples).


# Apiiro

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Apiiro](https://apiiro.com/) is an application security posture management (ASPM) platform that helps you understand and manage application security risks.

Integrating Apiiro with Cortex allows you to:

* [View risks on entity pages](#viewing-apiiro-risks-on-an-entity) in Cortex, quickly connecting issues to entities and their owners
* Use [Scorecards](#scorecards-and-cql) to drive quality improvements to your security practices relating to Apiiro applications, and set [Initiatives](/improve/initiatives) to prioritize tasks and set deadlines.

## How to configure Apiiro with Cortex

### Prerequisites

Before getting started:

* Create an [Apiiro API key](https://docs.apiiro.com/admin-apiiro/access-tokens). Include the following permissions:
  * `Risks > Read`
  * `Inventory management > Applications > Read`
  * `Inventory management > Repositories > Read`

### Configure the integration in Cortex

1. In Cortex, navigate to the [Apiiro settings page](https://app.getcortexapp.com/admin/integrations/apiiro).
   * Click **Integrations** from the main nav. Search for and select **Apiiro**.
2. Click **Add configuration**.
3. Configure the integration form:
   * **Alias**: Enter an alias for your configuration.
   * **API key**: Enter the API key you generated in Apiiro.
   * **Host**: Enter the base URL of your Apiiro instance. If left blank, the default host will be used.
4. Click **Save**.

After saving your configuration, you are redirected to the Apiiro integration settings page in Cortex. In the upper right corner of the page, click **Test configuration** to ensure Apiiro was configured properly.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Apiiro

### Discovery

Cortex uses the entity name, [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag), or repository as the "best guess" for the corresponding Apiiro application. For example, if your entity name is "My Service" or your tag is `my-service`, then the corresponding application name in Apiiro should also be My Service or `my-service`.

If your Apiiro application names don’t cleanly match the Cortex entity name or tag, you can override this in the Cortex entity descriptor.

### Editing the entity descriptor

You can define repositories and applications in the [entity descriptor](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file) under the `x-cortex-apiiro` block:

```yaml
x-cortex-apiiro:
  repositories:
    - alias: alias-one
      repositoryId: repository-one
    - alias: alias-two
      repositoryId: repository-two
  applications:
    - alias: alias-one
      applicationId: application-one
    - alias: alias-two
      applicationId: application-two
```

## Using the Apiiro integration

### Viewing Apiiro risks on an entity

#### Entity page overview

On an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details) overview, see risks listed under the **Code & security** block. Within this block, issues and vulnerabilities are grouped by severity: `Critical`, `High`, `Medium`, and `Low`. Click into any of these to open a list of all applicable issues and vulnerabilities.

#### Entity code & security sidebar

In an entity's sidebar, click **Code & security > Apiiro** to view risks from Apiiro.

### Scorecards and CQL

With the Apiiro integration, you can create Scorecard rules and write CQL queries based on Apiiro risks.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>List risks</summary>

List all risks for a given entity's Apiiro application.

**Definition**: `apiiro.risks()`

**Example**

A Scorecard's top level might include a rule to ensure that entities have a low number of Apiiro risks:

```
apiiro.risks().length < 3
```

</details>

<details>

<summary>Check if Apiiro application is set</summary>

Check if entity has a registered Apiiro application in its entity descriptor.

**Definition:** `apiiro ≠ null`

**Example**

An initial level in a security Scorecard might include a rule to make sure entities are associated with an Apiiro application. Without this, Cortex won't pick up data about applications in Apiiro:

```
apiiro != null
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# ArgoCD

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[ArgoCD](https://argoproj.github.io/cd/) is a declarative, GitOps continuous delivery tool for Kubernetes.

Integrating Cortex with ArgoCD allows you to:

* Send information about ArgoCD syncs into Cortex
  * This data appears on [entity detail pages](#view-argocd-data-on-entity-pages).
* Use [Cortex Workflows to automate ArgoCD syncs](#automate-argocd-events-in-workflows)
* See [deploy data for ArgoCD in Eng Intelligence](#see-argocd-data-in-eng-intelligence)

## How to configure ArgoCD with Cortex

### Step 1: Use ArgoCD notification webhooks

To send Cortex information about syncs in ArgoCD, use ArgoCD notification [Webhooks](https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/services/webhook/) to call the Cortex [deploy REST endpoint](/api/readme/deploys).

#### Example config map

Here is an example of what a `argocd-notifications-cm` config map may look like:

```yaml
apiVersion: v1
kind: ConfigMap
data:
  context: |
    argocdUrl: https://argo.company.com
  service.webhook.cortex-webhook: |
    url: https://api.getcortexapp.com
    headers:
    - name: Content-Type
      value: application/json
    - name: Accept
      value: application/json
    - name: Authorization
      value: Bearer $token 
    subscriptions: |
      - recipients:
        - cortex-webhook
        triggers:
        - on-sync-succeeded
  template.app-sync-succeeded: |
    webhook:
      cortex-webhook:
        method: POST
        path: /api/v1/catalog/{{.app.metadata.name}}/deploys 
        body: |
          { "customData": { "Sync Status": "{{.app.status.sync.status}}","Sync Details": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true" },
            "environment": "{{.app.spec.destination.name}}",
            "sha": "{{.app.status.operationState.operation.sync.revision}}",
            "timestamp": "{{.app.status.operationState.finishedAt}}",
            "title": "Sync by ArgoCD",
            "type": "DEPLOY"
          }
  trigger.on-sync-succeeded: |
    - send:
      - app-sync-succeeded
      when: app.status.operationState.phase in ['Succeeded']
        
```

This example assumes your ArgoCD application's name matches the `x-cortex-tag`. In this case, each application in ArgoCD can subscribe to the same trigger.

If your application name doesn't match the `x-cortex-tag`, add a value/pair to the info section of the Application manifest. Then, instead of using `.app.metadata.name` in the url path, use `{{(index .app.spec.info 0).value}}`.

### Step 2: Subscribe application to webhooks

Next, subscribe your application to the webhook. You do this by adding a label annotation in the Application spec in the following format:

```yaml
    notifications.argoproj.io/subscribe.<trigger-name>.<webhook-name>: ""
```

For example, if we want to subscribe an application to the example webhook above, the Application YAML may look like the following example:

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  annotations:
    notifications.argoproj.io/subscribe.on-sync-succeeded.cortex-webhook: ""
...  

```

## Using the ArgoCD integration

### View ArgoCD data on entity pages

After you configure the integration, you will see data about ArgoCD syncs in an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details):

* On the entity overview, ArgoCD syncs will appear under the **Latest events** section.\\

  <figure><img src="/files/gaKZMmMs7mfhiwqJCGI8" alt="ArgoCD syncs appear in the latest events on an entity."><figcaption></figcaption></figure>
* In the entity's sidebar, click **Events** to see a full list of events for the entity, including sync events from ArgoCD.
* In the entity's sidebar, click **CI/CD > Deploys** to see data from the [Cortex deploys API](/api/readme/deploys), including ArgoCD syncs.\\

  <div align="left"><figure><img src="/files/k6Eu2lT2RZFjrF9G8Xau" alt="ArgoCD data shows up on an entity page&#x27;s sidebar under CI/CD > Deploys." width="563"><figcaption></figcaption></figure></div>

### Automate ArgoCD events in Workflows

You can use a Workflow to automate ArgoCD syncs. [See this docs page for more information](https://github.com/cortexapps/hippocampus/blob/master/ingesting-data-into-cortex/integrations/broken-reference/README.md).

### See ArgoCD data in Eng Intelligence

Since the ArgoCD integration uses Cortex's [deploys API endpoint](/api/readme/deploys), ArgoCD data is included in Eng Intelligence deploy metrics. Learn more about [Eng Intelligence in the docs](/improve/eng-intelligence).

## Troubleshooting and FAQ

#### What permissions does my API Key need?

The API key needs to be able to call the[ "Add deployment for entity"](https://docs.cortex.io/api/rest/deploys#post-api-v1-catalog-tagorid-deploys) API endpoint, so ensure the `Edit entities` permission is enabled.

#### Ensure the Cortex API Key is encoded correctly

Make sure the encoded Cortex API Key does not contain an extra line. Use a tool like <https://www.base64encode.org/> to ensure your encoded key does not contain an extra line.

#### Check the ArgoCD logs

The notification webhook is managed by the `argocd-notifications-controller` which will have a pod running in your ArgoCD namespace.

Assuming the ArgoCD is running in the `argocd` namepsace, run the following command to get the list of pods:

`kubectl get pods -n argocd`

This will return a list of pods similar to the ones listed below:

```
NAME                                                READY   STATUS    RESTARTS   AGE
argocd-application-controller-0                     1/1     Running   0          108d
argocd-applicationset-controller-69f96ccf5b-5jnpv   1/1     Running   0          108d
argocd-dex-server-5dff9c5998-j29zd                  1/1     Running   0          80d
argocd-notifications-controller-6cd988b564-sql55    1/1     Running   0          107d
argocd-redis-54c687db9d-kdxwj                       1/1     Running   0          80d
argocd-repo-server-6c6f8859c7-mrwll                 1/1     Running   0          108d
argocd-server-b77b48886-s2mtg                       1/1     Running   0          80d
```

In this example, the pod managing the webhook notifications is `argocd-notifications-controller-6cd988b564-sql55`. To get the logs, run the following command:

`kubectl logs argocd-notifications-controller-6cd988b564-sql55 -n argocd`

If your trigger was successful, you should seem something similar to this:

```
time="2023-07-19T02:41:13Z" level=info msg="Start processing" app=argocd/app-direct
time="2023-07-19T02:41:13Z" level=info msg="Trigger on-sync-succeeded result: []" app=argocd/app-direct
time="2023-07-19T02:41:13Z" level=info msg="Notification about condition 'on-sync-succeeded.[0].zxM90Et6k4Elb1-fHdjtDJq0xR0' already sent to ''" app=argocd/app-direct
time="2023-07-19T02:41:13Z" level=info msg="Processing completed" app=argocd/app-direct
```

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# AWS

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Amazon Web Services (AWS)](https://aws.amazon.com/) provides on-demand cloud computing platforms and APIs.

Integrating Cortex with AWS allows you to:

* Track AWS entities in the catalog
* Automatically discover and track ownership of AWS entities and dependencies
  * You can also [enable auto-import](#enable-automatic-discovery-of-aws-entities) of any discovered entities of known types.
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your AWS resources

If you are on a self-hosted Cortex instance, see the [self-managed AWS setup](/self-managed/features/integrations/aws) page.

## How to configure AWS with Cortex

### Step 1: Configure the integration in Cortex

1. In Cortex, navigate to the [AWS settings page](https://app.getcortexapp.com/admin/integrations/aws).
   * Click **Integrations** from the main nav. Search for and select **AWS**.
2. Click **Add configuration**.
3. In the modal, the JSON configuration, Cortex AWS account ID, and External ID are displayed. In the configuration side bar instructions, you will also see the option to copy a starting "Read Only Access" JSON policy. Keep this browser window open, as you will need these in the next steps.

### Step 2: Set up an IAM policy in AWS

{% hint style="info" %}
When using Cloud Control, the role Cortex assumes to get access into your account needs to have read access to all the selected types. This access is included by default in the Read Only Access policy in Cortex, or it can be configured manually for each type.
{% endhint %}

For each account:

1. Log in to your AWS Management Console and open the [IAM console](https://console.aws.amazon.com/iam/).
2. Click **Policies**, then choose **Create policy**.
3. Switch to the JSON editor. In Cortex while configuring AWS, copy the JSON "Read Only Access" starting policy that appears in the in-app instructions. Paste it into the JSON editor.
   * This policy allows Cortex to list all resources, resource types, and resource tags.
   * If you choose to configure this manually, rather than using the starting policy provided, insert a valid IAM policy depending on the resource types you'd like to import. For example, if you want to import resources of type `AWS::IAM::role`, we'll need to have permission to `iam:ListRoles`, `iam:ListAttachedRolePolicies`, `iam:GetRole`, `iam:ListAccountAliases` and `iam:ListRolePolicies`.
     * For manual configurations, make sure to add the `cloudformation:ListTypes`, `cloudformation:ListResources`, and `cloudformation:GetResource` permissions so that we can pull the list of types available from AWS.
4. Click **Review Policy**, enter a name, then click **Create Policy**.

See the AWS documentation for more information: [Create IAM policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create-console.html).

### Step 3: Create a role in AWS

This section is specific to cloud-based Cortex accounts. If you are on a self-hosted Cortex instance, please see the AWS account setup guide for self-hosted Cortex.

1. In AWS, navigate to **Roles > Create Role**.
2. For the trusted entity type, select **Another AWS account**.
3. In the **Account ID** field, enter the Cortex AWS account ID that was displayed in Cortex in the earlier steps.
4. Click **Require External ID**, then enter the Cortex external ID that was displayed in Cortex in the earlier steps.
5. Click **Next**.
6. Select your newly created policy, and click **Next**.
7. Enter a name for your role. Optionally, configure tags. When you are finished, click **Create Role**.
8. Search for your new role in the list and copy its name. You will need this in the next steps.
9. In the upper right corner of AWS, click your name. In the dropdown that appears, copy your AWS account ID. You will need these in the next steps.

Note that if you use multiple AWS accounts, they will share a common rotatable `externalId`.

### Step 4: Finish the configuration in Cortex

1. Navigate back to the browser window containing your [Cortex AWS settings page](https://app.getcortexapp.com/admin/settings/aws).
2. Configure the AWS integration form:
   * **Account ID**: Enter the AWS account ID you obtained in the previous steps.
   * **IAM role**: Enter the role name you obtained in the previous steps.
3. Click **Save**.

### Step 5: Select AWS resource types

In your [AWS integration settings page](https://app.getcortexapp.com/admin/settings/aws?activeTab=settings) in Cortex, Cortex will pull all the types you included in the IAM policy into the **Cloud Control types** dropdown.

{% hint style="warning" %}
If any resource types do not appear in the list, ensure that `cloudformation:ListTypes`, `cloudformation:ListResources`, and `cloudformation:GetResource` are added to the IAM policy so Cortex can pull the list of all available types from AWS.
{% endhint %}

To select your cloud control types:

1. In the **Cloud control types** field, select the types you want Cortex to discover.
   * If [automatic import](#enable-automatic-import-of-aws-entities) is enabled, then these types will automatically be imported into Cortex.
     * If you later need to remove any auto-imported cloud control types, see [the FAQ below](#if-i-have-auto-import-enabled-how-can-i-remove-cloud-control-types-that-i-no-longer-want-to-be-impor).
2. Click **Save cloud control types**.

If the type you're looking to import is in the list below, please reach out to <support@cortex.io> to submit a feature request.

The following Cloud Control types are not currently supported:

```
AWS::ApiGateway::DocumentationVersion
AWS::ApiGateway::Step
AWS::CloudFormation::ResourceVersion
AWS::CustomerProfiles::Integration
AWS::CustomerProfiles::ObjectType
AWS::EC2::TransitGatewayMulticastGroupMember
AWS::EC2::TransitGatewayMulticastGroupSource
AWS::ECS::TaskSet
AWS::Glue::Attach::SchemaVersion
AWS::Glue::Attach::SchemaVersionMetadata
AWS::IoTSiteWise::AccessPolicy
AWS::IoTSiteWise::Dashboard
AWS::IoTSiteWise::Project
AWS::Kendra::DataSource
AWS::Kendra::Faq
AWS::MediaConnect::FlowEntitlement
AWS::MediaConnect::FlowOutput
AWS::MediaConnect::FlowSource
AWS::MediaConnect::FlowVpcInterface
AWS::MediaPackage::Asset
AWS::MediaPackage::PackagingConfiguration
AWS::NetworkFirewall::LoggingConfiguration
AWS::QuickSight::Analysis
AWS::QuickSight::Dashboard
AWS::QuickSight::DataSet
AWS::QuickSight::DataSource
AWS::QuickSight::Template
AWS::QuickSight::Theme
AWS::RDS::DBProxyTargetGroup
AWS::S3Outposts::AccessPoint
AWS::S3Outposts::Bucket
AWS::SSO::Assignment
AWS::SSO::InstanceAccessControlAttributeConfiguration
AWS::SSO::PermissionSet
```

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to AWS

{% hint style="info" %}
For AWS, Cortex replaces non-alphanumeric characters in entity names with a space. For example, `resource_1` would become `resource 1`.

For the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag), Cortex replaces non-alphanumeric characters with `-` and lowercases the letters. If multiple special characters appear together in a tag, Cortex replaces the group of characters with only one `-`. For example, `mY_e%ntity#$_tag` would become `my-e-ntity-tag`.
{% endhint %}

### Enable automatic import of AWS entities

You can configure automatic import from AWS:

1. In Cortex, navigate to the [Entities Settings page](https://app.getcortexapp.com/admin/settings/entities/general).
2. Next to **Auto import from AWS, Azure, and/or Google Cloud**, click the toggle to enable the import.\\

   <figure><img src="/files/p4fNmdV0qFSbUMX1YwGD" alt=""><figcaption></figcaption></figure>

If you do not have automatic import enabled, you can [manually import](#import-entities-from-aws).

### Limit discovery to specific regions

By default, Cortex will search for resources across all AWS regions, but you can limit that to specific regions in the [Cortex AWS settings page](https://app.getcortexapp.com/admin/settings/aws).

### Import entities from AWS

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on importing entities.

### Discover dependencies for AWS

Cortex automatically discovers dependencies between your services and resources by scanning for resources with specific AWS tags. By default, a service will have dependencies on any Cortex resource that has a corresponding AWS resource with [AWS tag](https://docs.aws.amazon.com/tag-editor/latest/userguide/tagging.html) key = "service" and tag value = the service's Cortex tag.

#### Customize AWS tag names

In Cortex under the [AWS integration page](https://app.getcortexapp.com/admin/settings/aws?activeTab=settings), you can customize the tag key names. Expand the **Dependencies sync from AWS** section, then select tags from the dropdown menu. Note that an `AND` operator is used when you select multiple tags; the resource will need to have all specified tags in order to be recognized by Cortex.

If you do not specify tag names, Cortex will use "service" as the key name.

#### AWS dependency sync

Cortex syncs AWS tags daily at 8 a.m. UTC. To manually refresh the tags, navigate to the [relationship graph](https://app.getcortexapp.com/admin/graph) in your workspace, click the menu in the upper right corner, then click **Sync dependencies**.

<div align="left"><figure><img src="/files/oRNSrQmLhBxgzXa8Mpii" alt=""><figcaption><p>Sync dependencies in the relationship graph.</p></figcaption></figure></div>

**Use key/value pairs in the entity descriptor for discovery**

You can also use explicit tag key/value pairs in the `x-cortex-dependency` block for AWS dependency discovery. Instead of making a service depend on a resource based on service tags, Cortex will make a service depend on a resource if any of the resource's AWS tags match the explicitly defined key/value pairs in the service's `x-cortex-dependency` block. For example, the service below will have dependencies on any AWS resource with tag (key = `aws:cloudformation:my-key-1`, value = `arn:aws:cloudformation:my-region:my-value-1`) or tag (key = `aws:cloudformation:my-key-2`, value = `arn:aws:cloudformation:my-region:my-value-2`).

```yaml
x-cortex-dependency:
  aws:
    tags:
      - key: my-key-1
        value: my-value-1
      - key: my-key-2
        value: my-value-2
      - key: "aws:cloudformation:my-key-1"
        value: "arn:aws:cloudformation:my-region:my-value-1"
      - key: "aws:cloudformation:my-key-2"
        value: "arn:aws:cloudformation:my-region:my-value-2"
```

For more information on dependencies, see the [Dependencies documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/dependencies).

### Discover ownership for AWS

Cortex can automatically discover ownership for your AWS resources. To enable this, make sure that your AWS resources have a tag matching the `x-cortex-tag` of the corresponding Cortex team and enable the “Sync ownership from AWS” toggle in the Settings page. By default, we look for the `owner` tag. You can also customize the tag key name.

Cortex syncs ownership from AWS every day at 6 am UTC.

### Editing the entity descriptor

We recommend [automatically importing your AWS entities](#enable-automatic-import-of-aws-entities) for the fastest and most efficient experience connecting your data. If you need to manually edit entity descriptors, see the information below.

You can associate a Cortex entity with one or more AWS entities. For certain AWS resource types, Cortex will display those AWS entities' metadata on the Cortex entity page.

```yaml
x-cortex-infra:
  aws:
    cloudControl:
    - type: AWS::RDS::DBInstance
      region: us-west-2
      accountId: "123456123456"
      identifier: rds-example
```

**Multiple ECS services on a single entity**

You can associate a Cortex entity with multiple ECS services.

If you are using the Cloud Control resource types, use the format below:

```yaml
x-cortex-infra:
  aws:
    cloudControl:
    - type: AWS::ECS::Service
      region: us-west-2
      accountId: "123456123456"
      identifier: ecs-example
    - type: AWS::ECS::Service
      region: us-west-2
      accountID: "34567345673"
      identifier: ecs-example-2
```

If you are not using Cloud Control types or if you imported your entity prior to Cortex supporting Cloud Control types, you can use the format shown below:

```yaml
x-cortex-infra:
  aws:
    ecs:
      - clusterArn: abcd
        serviceArn: efgh
      - clusterArn: stuv
        serviceArn: wxyz
```

The values for `clusterArn` and `serviceArn` are defined in [ECS](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html).

#### Discovery audit

Cortex will pull recent changes from your AWS environment into the [discovered entities list](/ingesting-data-into-cortex/entities-overview/entities/discovery-audit). Here, you can find new entities in AWS that have not been imported into the catalog - these will have the tag **New AWS Resource** - as well as entities in the catalog that no longer exist in AWS - these will have the tag **AWS Resource Not Detected**.

## Using the AWS integration

### Searching AWS entities in Cortex

The following keys are supported when searching for your AWS entities in Cortex under **Catalogs > All Entities**:

* `aws-account-id` - Account ID number
* `aws-account-name` - Account alias
* `aws-region` - AWS region of the resource
* `aws-type` - AWS type of the resource
* `aws-name` - AWS name of the resource
* `aws-identifier` - The primary identifier of a resource
* `aws-secondary-identifier` - The secondary identifier of a resouce

#### Example search queries

* `aws-type:"AWS::EC2" AND aws-region:"us-west"`: Search for entities of category EC2 in the any of us-west regions
* `aws-account-id: "234512324"`: Search for all entities from the account 234512324
* `aws-name:"aws-identifier-of-resource" AND aws-account-name:"test-account"`: Search for entity with identifier aws-identifier-of-resource in the account with alias test-account

<figure><img src="/files/CLuDs2PpIvHDOx2mlqxl" alt=""><figcaption></figcaption></figure>

### Scorecards and CQL

With the AWS integration, you can create Scorecard rules and write CQL queries based on AWS resources.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>AWS details</summary>

Get the AWS details for an entity

**Definition:** `aws.details(): Object`

**Example**

In a Scorecard, you can create a rule to verify that an entity of type `lamda` has a correct function name:

```
aws.details().resources.filter((resource) => resource.typeName == "AWS::Lambda::Function").length > 0
```

You could also create a rule to verify that an entity is not using deprecated runtimes:

```
aws.details().resources.filter((resource) => resource.typeName == "AWS::Lambda::Function" and resource?.metadata?.get("Runtime")?.matchesIn("(python3\\.6|python2\\.7|dotnetcore2\\.1|ruby2\\.5|nodejs12\\.|nodejs10\\.|nodejs8\\.10|nodejs4\\.3|nodejs6\\.10|dotnetcore1\\.0|dotnetcore2\\.0|nodejs4\\.3-edge|nodejs$)")).length == 0    
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

### Background sync

Cortex conducts the following background syncs for AWS:

* Ownership sync daily at 6 a.m. UTC
* AWS tag sync (dependencies) daily at 8 a.m. UTC
  * You can [sync dependencies manually](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/dependencies#sync-dependencies) via the Relationship Graph.
* Integration details daily at 10 a.m. UTC

## Troubleshooting and FAQ <a href="#still-need-help" id="still-need-help"></a>

#### If I have auto-import enabled, how can I remove cloud control types that I no longer want to be imported?

If you want to remove any of the cloud control types after importing them: Disable the [automatic import](#enable-automatic-import-of-aws-entities) setting, remove the cloud control types from your [AWS integration settings](#step-5-select-aws-resource-types), then enable [auto-archival](/configure/settings/entity-settings/auto-archive). This will cause the removed cloud control types to be archived during the next sync.

#### Why am I seeing the AWS account ID instead of the AWS account alias?

We've recently added support for pulling in the AWS account alias. The required permission is `iam:ListAccountAliases` (see the AWS documentation [here](https://000001.awsstudygroup.com/1-create-new-aws-account/1.3-aws-account-alias/#create-or-edit-an-account-alias)). Once this permission is added, the we will persist the account alias everywhere instead of the ID.<br>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Azure DevOps

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Azure DevOps](https://azure.microsoft.com/en-us/products/devops) is a Microsoft-owned version control system used for managing the software development lifecycle.

Integrating Cortex with Azure DevOps allows you to:

* Automatically discover and track ownership of Azure DevOps entities
* Follow a GitOps workflow with Azure DevOps
* View information about your Azure DevOps repositories on an entity's details page, including: The repo associated with the entity, recent commits and releases in the event timeline, the most-used language in the files for that entity, the top code contributors, and their number of contributions
  * If you pull in [Azure DevOps pipeline data](#define-pipelines), you can also see pipeline runs and builds in the CI/CD section of an entity's details page.
  * If you enable the [option to pull in Azure DevOps work items](#enable-or-disable-azure-devops-work-items), you will also see a list of open work items on entity pages.
* View information about pull requests and work items in the engineering homepage
* [Create a work item from an Initiative issue](#create-a-work-item-from-an-initiative-issue) in Cortex
* Use Azure DevOps metrics in Eng Intelligence to understand key metrics and gain insight into services, incident response, and more
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your repositories, Azure DevOps work items, and Azure DevOps pipeline data

## How to configure Azure DevOps with Cortex

### Configure the integration in Cortex

You can configure Azure DevOps with a Personal Access Token (PAT) or with a Service Principal with Entra ID.

{% tabs %}
{% tab title="Personal Access Token" %}
**Prerequisite**

Before you get started:

* Add a [Azure DevOps personal access token](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate) with at least the following scopes enabled:
  * Analytics: `read`
  * Build: `read`
  * Code: `read`
    * If using the [Scaffolder](/streamline/workflows/scaffolder) with Azure DevOps, you must also enable:
      * Code: `write`
      * Code: `manage`
  * Graph & Identity: `read`
  * Work Items: `read` and `write`

**Configure the Azure DevOps integration with a PAT**

1. In Cortex, navigate to the [Azure DevOps settings page](https://app.getcortexapp.com/admin/integrations/azuredevops).
   * Click **Integrations** from the main nav. Search for and select **Azure DevOps**.
2. Click **Add configuration** and select **Personal Access Token**.
3. Configure the Azure DevOps integration form:
   * **Organization**: Enter the slug for your Azure DevOps organization.
   * **Username**: Enter the username for your personal access token.
   * **Personal access token**: Enter your Azure DevOps personal access token.
   * **Host**: Optionally, if you are using a self-managed setup, enter your hostname.
4. Click **Save**.
   {% endtab %}

{% tab title="Service Principal" %}
**Prerequisite**

Before you get started:

* In your Azure portal under **Entra ID > App registrations**, [set up an app registration](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app#add-credentials).
  * You will need the Client ID and Azure Tenant ID associated with this app registration.
  * When you create an app registration, a Service Principal user is also generated.
* In your Azure portal, create a Client Secret for your app registration.
  * While viewing the overview of your app registration, click the link next to "Client credentials." You will be directed to the **Certificates & secrets** page, where you can click **+New client secret** to create a secret.

**Step 1: Add your Service Principal to your Azure DevOps organization**

You must add the Service Principal user to the organization you're integrating with Cortex.

1. In Azure DevOps, from the list of organizations, select the one you will be integrating with Cortex.
2. Navigate to **Organization Settings > General > Microsoft Entra**. Connect your Entra ID directory (the one containing the app registration) with the Azure DevOps organization.
3. Navigate to **Organization Settings > General > Users,** then click **Add users**.
4. In the side panel, configure the new user:
   * **Users or Service Principals**: Enter the Service Principal associated with your app registration.
   * **Access level**: Select `Basic`.
   * **Add to projects**: Add the user to the project(s) that your Cortex integration will need access to.
   * **Azure DevOps Groups**: Select security groups. `Project Contributors` should be sufficient, or you can choose a custom security group that has Code write permissions.
     * Learn more about [permissions for Service Principals in Azure's documentation](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity?view=azure-devops#step-3-configure-permissions).
5. At the bottom of the side panel, click **Add**.

**Step 2: Configure the Azure DevOps integration in Cortex**

1. In Cortex, navigate to the [Azure DevOps settings page](https://app.getcortexapp.com/admin/integrations/azuredevops).
   * Click **Integrations** from the main nav. Search for and select **Azure DevOps**.
2. Click **Add configuration** and select **Service Principal**.
3. Configure the Azure DevOps integration form:
   * **Category**: Select which integration categories this configuration will apply to.
   * **Configuration alias**: Enter an alias for this configuration.
   * **Organization**: Enter the slug for your Azure DevOps organization.
   * **Client ID**: Enter the Application Client ID for your app registration.
   * **Client Secret**: Enter the Client Secret for your app registration.
   * **Azure Tenant ID**: Enter the Directory (Tenant) ID for your app registration.
   * **Host**: Optionally, if you are using a self-managed setup, enter your hostname.
4. Click **Save**.
   {% endtab %}
   {% endtabs %}

Cortex supports mapping multiple identities for a single user if you have multiple configurations of Azure DevOps. See the [Identity mapping documentation](/configure/settings/managing-users/identity-mapping) for more information.

#### **Enable or disable Azure DevOps work items**

On the [Azure DevOps settings page in Cortex](https://app.getcortexapp.com/admin/settings/azuredevops), you can choose whether Azure DevOps work items should be pulled in from Azure DevOps. Cortex recommends disabling this option if your organization does not use work items or if you are worried about running into rate limit issues.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Azure DevOps

### Import entities from Azure DevOps

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on importing entities.

### Editing the entity descriptor

In an entity's YAML, you can define a [repository](#define-a-repository), [work items](#define-work-items), [ownership](#define-ownership), and [pipelines](#define-pipelines).

#### **Define a repository**

To define an Azure DevOps repository for a given entity, add the `x-cortex-git` block to the entity's descriptor.

```yaml
x-cortex-git:
  azure:
    project: cortex
    repository: docs
    basepath: myService
    alias: accountAlias
```

| Field        | Description                                                                                                                                | Required |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | -------- |
| `project`    | The name of the project as listed under the "Projects" tab when you are logged into Azure DevOps (on the <https://dev.azure.com//> screen) | **✓**    |
| `repository` | The repo name you see when you navigate to the "Repos" section of Azure DevOps                                                             | **✓**    |
| `basepath`   | If the entity is in a monorepo (e.g. in a subdirectory), use this field to define the subdir                                               |          |
| `alias`      | Alias for the configuration in Cortex (only needed if you have opted into multi-account support)                                           |          |

Only one repository can be defined for in a given entity's YAML in the `x-cortex-git` block.

#### **Define work items**

Before adding work items to your entity YAML, make sure you have [enabled the option to pull in Azure DevOps work items](#enable-or-disable-azure-devops-work-items) in your integration settings.

To define Azure DevOps work items for a given entity, add the `x-cortex-azure-devops` block to the entity's descriptor. If there is no work item registrations, but the entity matches a repository, we will pull in all work items from the repository's project with a tag that matches the Cortex entity name, [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag), or the repository name.

<details>

<summary>Example WIQL</summary>

The example YAML below is based on the following example WIQL:

```
SELECT
    [System.Id],
    [System.AssignedTo],
    [System.State],
    [System.Title],
    [System.Tags]
FROM workitems
WHERE
    '[System.TeamProject] = Design Agile'
    AND '[System.WorkItemType] = User Story'
    AND '[System.State] = Active'
ORDER BY [System.ChangedDate] DESC
ASOF '02-11-2020'
```

Learn more about WIQL in [Microsoft's WIQL syntax reference](https://learn.microsoft.com/en-us/azure/devops/boards/queries/wiql-syntax?view=azure-devops).

</details>

```yaml
x-cortex-azure-devops:
    workItems:
        projects:
            - name: projectName1
              wiqls:
                - "[System.TeamProject] = 'Design Agile'"
                - "[System.WorkItemType] = 'User Story'"
                - "[System.State] = 'Active'"
                - ORDER BY [System.ChangedDate] DESC ASOF '02-11-2020'
            - name: projectName2
              alias: alias1
            - name: projectName3
              alias: alias2
```

| Field      | Description                                                                                                                         | Required |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `projects` | List of the projects                                                                                                                | **✓**    |
| `name`     | The project name as listed under the "Projects" tab when you are logged into Azure DevOps (on the <https://dev.azure.com//> screen) | **✓**    |
| `wiqls`    | List of WIQL conditions to filter work items fetched                                                                                |          |
| `alias`    | Alias for the configuration in Cortex (only needed if you have opted into multi-account support)                                    |          |

#### **Define ownership**

Ownership of each entity through Azure DevOps is defined through an owner of type `group`.

```yaml
x-cortex-owners:
  - type: group
    name: My Azure DevOps Team
    provider: AZURE_DEVOPS
    description: This is a description for this owner # optional
```

`name` is a case-sensitive field that corresponds to the upstream identifier of your owner from Azure DevOps.

Learn more about ownership in [Defining ownership](/ingesting-data-into-cortex/entities-overview/entities/ownership).

#### Define pipelines

You can add Azure DevOps pipelines under the `x-cortex-azure-devops` block:

```yaml
  x-cortex-azure-devops:
    pipelines:
      projects:
      - name: projectName1
        alias: config-1
        pipelines:
        - id: 1
      - name: projectName2
        alias: config-2
        pipelines:
        - id: 2
```

| Field          | Description                                                                                                                         | Required |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `piepelines`   | List of the pipelines                                                                                                               | **✓**    |
| `projects`     | List of the projects                                                                                                                | **✓**    |
| `name`         | The project name as listed under the "Projects" tab when you are logged into Azure DevOps (on the <https://dev.azure.com//> screen) | **✓**    |
| `alias`        | Alias for the configuration in Cortex (only needed if you have opted into multi-account support)                                    |          |
| `pipelines:id` | The Azure DevOps `system.definitionID` for the pipeline.                                                                            | **✓**    |

Learn more about Azure DevOps pipelines in [Microsoft's documentation](https://learn.microsoft.com/en-us/azure/devops/pipelines/get-started/what-is-azure-pipelines?view=azure-devops).

### Identity mappings for Azure DevOps

Cortex maps users' email addresses to discovered Azure DevOps accounts.

You can confirm users' Azure DevOps accounts are connected from [Azure DevOps identity mappings in settings](https://app.getcortexapp.com/admin/settings/azuredevops-mappings).

### Create a work item from an Initiative issue

Initiatives allow you to set deadlines for specific rules or a set of rules in a given Scorecard and send notifications to users about upcoming due dates.

From the Issues tab of an Initiative, you can automatically create a Azure DevOps work item from a failing rule:

1. Click **Create issue**.
2. In the modal that appears, fill out the form:
   * **Integration**: If you have multiple task tracking tools, select Azure DevOps from the Integration dropdown.
   * **Name**: Enter a name for the configuration.
   * **Project**: Select from the dropdown.
     * Options available in the dropdown are pulled in from the specific Azure DevOps instances configured in Settings.
3. Select the [**Work item type**](https://learn.microsoft.com/en-us/azure/devops/boards/work-items/about-work-items?view=azure-devops\&tabs=agile-process/) and the **Sub-item Type** from the respective dropdowns. Then, select how the sub-items's fields should be populated on issue creation and status change.
4. Choose to include or exclude groups of entities, or define a more advanced filter.

The issue configuration will apply to all entities that meet the filter criteria. Once an entity is passing the rule, Cortex will automatically close the associated ticket.

## Using the Azure DevOps integration

### View Azure DevOps data on entity pages in Cortex

The Azure DevOps integration will populate the **Repo** detail block on an entity's details page.

In the **Recent activity preview**, you'll find the recent commits and releases. These will also appear in the event timeline.

These data will appear for entities imported from a Git source or those that have a Git repo defined in their YAMLs.

#### **Events**

On an entity's **Events** page, you can find all of the commits and releases associated with that entity. Each is hyperlinked to the commit or release page in Azure DevOps and includes a timestamp.

#### **CI/CD**

From the **CI/CD > Deploys** page in the entity's sidebar, see a history of pipeline runs.

#### **Repository**

You can access more detailed information pulled from Azure DevOps under **Repository** in the sidebar. At the top of the repository page, you'll find the repo associated with that entity and the most-used language in files for that entity. In the **Top contributors** block, you'll find the three users who have contributed the most code and the number of their contributions.

In the **Commits** section, you'll find the 10 most recent commits and metadata about each. Below **Commits** is the **Recent releases** section, which includes the 5 most recent releases.

#### **Issue tracking**

In the **Issue tracking** section, you can find a list of open [Azure DevOps work items](https://learn.microsoft.com/en-us/azure/devops/boards/work-items/about-work-items?view=azure-devops\&tabs=agile-process). Each work item will show the title, summary, assignees, priority, and date created.

#### **Packages**

Packages are automatically scraped from your Git repos or they can be submitted via the [packages API](/api/readme/packages). The package file must be in the root of your repository — or, if you're using `basepath`, in the root of the subdirectory — to be scraped by Cortex. You can query an entity's packages in [CQL explorer](https://app.getcortexapp.com/admin/cql-explorer) using `packages()`.

To view packages, click **Packages** in the entity's sidebar.

The following package types are automatically scraped from repositories:

* JavaScript / Node.js: `package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`
* Python: `requirements.txt`, `pipfile.lock`
* .NET (C#): `packages.lock.json`
* Java: `pom.xml`
* Go: `go.sum`

All other files of these types can be added via the [packages API](/api/readme/packages).

### Engineering homepage

The Azure DevOps integration enables Cortex to pull information about pull requests and work items into the [homepage](/streamline/homepage). You can find your open pull requests, any pull requests assigned to you for review, and any work items assigned to you.

Pull requests and work items from Azure DevOps are refreshed every 5 minutes.

### Eng Intelligence

The [Eng Intelligence tool](https://app.getcortexapp.com/admin/eng-intelligence) also uses pull request data from Azure DevOps to generate metrics:

* Average PR open to close time
* Avg time to first review
* Avg time to approval
* PRs opened
* Weekly PRs merged
* Avg PRs reviewed/week
* Avg commits per PR

Read more about how Eng Intelligence tracks metrics for teams and users in the [Eng Intelligence documentation](/improve/eng-intelligence).

### Scorecards and CQL

With the Azure DevOps integration, you can create Scorecard rules and write CQL queries based on Azure DevOps work items.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Approvals required to merge</summary>

Total number of approval required to merge a pull request into a repository. Defaults to 0 if no approvals are defined.

**Definition:** `git.numOfRequiredApprovals()`

**Examples**

For a security or development maturity Scorecard, you can write a rule to make sure at least one approval is required for a pull request:

```
git.numOfRequiredApprovals() >= 1
```

By having a rigorous PR process in place for a repo, you can make sure changes aren't made that create vulnerabilities. This kind of rule could also be used in a best practices or project standards Scorecard.

You can also use a similar expression in the Query Builder to find entities lacking approval:

```
git.numOfRequiredApprovals() < 1
```

</details>

<details>

<summary>Branches</summary>

List all live branches with some basic metadata:

* Head
* Is protected
* Name

**Definition:** `git.branches(): List<GitBranch>`

**Example**

For a development best practices Scorecard, you can make sure that branches associated with an entity match a standard naming convention:

```
git.branches().all((branch) => branch.name.matches("(main|master|feat-.*|bug-.*|task-.*
```

</details>

<details>

<summary>Branch protection details</summary>

Find details for a specified branch or default branch if none is specified.

**Definition:** `git.branchProtection(branchName: Text?): GitBranchProtection`

**Examples**

For a security Scorecard, you can write a rule to make sure the default branch is protected:

```
git.branchProtection() != null
```

Or to make sure the main branch is protected:

```
git.branchProtection("main") != null
```

Because vulnerabilities in the default branch are critical, this rule should be in one of the first couple levels. A higher-level rule might make sure that branch protection checks are set:

```
git.branchProtection("main").requiredStatusChecks.length > 0
```

You can also use the Query Builder to find entities with unprotected default branches:

```
git.branchProtection() = null
```

</details>

<details>

<summary>Commits</summary>

Get the latest commits (to a maximum of 100) for a defined lookback period (defaulting to 7 days).

These results can be filtered based on branch name, using the default branch if no other branch is provided.

**Definition:** `git.commits()`

**Examples**

You can use the `git.commits()` expression in a security Scorecard to make sure entities have fewer than three commits to a "security-fixes" branch in the last week:

```
git.commits(branch="security-fixes").length < 3
```

Entities passing this rule will include those that haven't needed three or more security fixes. This can indicate that there aren't vulnerabilities in a given entity's code, but could also suggest that fixes aren't being implemented.

Using this rule in conjunction with one focused on vulnerabilities could provide the extra context needed to gain a better understanding of what's happening.

</details>

<details>

<summary>Default branch</summary>

Default branch for the entity's repository or `main` when null.

**Definition:** `git.defaultBranch()`

**Examples**

If default branches should always be named "main," you can write a rule in a best practices Scorecard to make sure entities are compliant:

```
git.defaultBranch().matches("main")
```

</details>

<details>

<summary>File contents</summary>

Load the contents of a file from the entity's associated repository.

The contents can be validated by using string comparison operations or parsed by the built-in `jq` function. The `jq` function will automatically coerce file contents of JSON or YAML formats.

**Definition:** `git.fileContents(<filename: Text>)`

**Examples**

For a Scorecard focused on development maturity, you could use the `git.fileContents()` rule to enforce that a CI pipeline exists, and that there is a testing step defined in the pipeline:

```
git.fileContents(“circleci/config.yml”).matches(“.*npm test.*”) - Enforce that a CI pipeline exists, and there is a testing step defined in the pipeline
```

A best practices Scorecard, meanwhile, could use this expression for a number of rules:

* To make sure node engine version in specified in the `package.json` file:

  ```
  jq(git.fileContents("package.json"), ".engines.node") != null
  ```
* To make sure TypeScript projects have a `tsconfig.json` file checked in:

  ```
  jq(git.fileContents("package.json"), ".devDependencies | with_entries(select(.key == \"typescript\")) | length") == 0 or git.fileExists("tsconfig.json")
  ```
* To make sure projects using yarn do not allow NPM:

  ```
  jq(git.fileContents("package.json"), ".engines.yarn") == null or jq(git.fileContents("package.json"), ".engine.npm") = "please-use-yarn"
  ```
* And to ensure the yarn version being used is not deprecated:

  ```
  jq(git.fileContents("package.json"), ".engines.yarn") == null or !(semver("1.2.0") ~= semverRange(jq(git.fileContents("package.json"), ".engines.yarn")))
  ```

</details>

<details>

<summary>File exists</summary>

Check if file exists from within the entity's associated repository.

**Definition:** `git.fileExists(<filename: Text>)`

**Examples**

For a development best practices Scorecard, this expression can be used for a rule that makes sure developers are checking in lockfiles to ensure repeatable builds:

```
git.fileExists(“package-lock.json”)
```

In the Query builder, you can use this expression with a wildcard to find entities with unit tests enabled:

```
git.fileExists(*Test.java”)
```

Or to find entities with an outdated Terraform version:

```
git.fileExists("terraform/versions.tf") and !git.fileContents("terraform/versions.tf").matchesIn("required_version =! \"[~>= ]{0,3}0\\.(12|13)")
```

</details>

<details>

<summary>Has Cortex YAML (GitOps)</summary>

When enabling GitOps to manage entity descriptors, Cortex checks for a checked in file `./cortex.yaml` at the root directory. This rule can help track migrations from UI editing to GitOps for entity descriptor management.

**Definition:** `git.hasCortexYaml()`

**Examples**

If you're using a Scorecard to track a migration from Cortex UI to GitOps, you can use this rule to make sure entities are set up for GitOps management of entity descriptors:

```
git.hasCortexYaml() == true
```

</details>

<details>

<summary>Git repository set</summary>

Check if entity has a registered Git repository.

**Definition:** `git (==/!=) null`

**Examples**

A Scorecard focused on best practices or standards will likely include a rule in its first level making sure a Git repository is set up:

```
git != null
```

If an entity is failing this rule, it can indicate broader issues with the integration or explain why an entity isn't functioning as expected.

</details>

<details>

<summary>Last commit details</summary>

Provides last commit details.

**Definition:** `git.lastCommit()`

**Examples**

Depending on best practices at your organization, you may want to confirm the last commit for a given entity is no older than 3 days:

```
datetime(git.lastCommit().date).fromNow() > duration("P-3D")
```

Confirming whether a service was updated recently can help team members catch outdated code sooner. Plus, if there is a security issue, you can quickly determine which services have or have not been updated to patch the vulnerability.

For a best practices Scorecard, you can also use this expression to make sure the entity's last commit message follows conventional commit guidelines:

```
git.lastCommit().message.matches("^(feat|fix|docs|style|refactor|test|chore)(\\(.+\\))?:*")
```

</details>

<details>

<summary>List pipelines</summary>

List pipelines with metadata, including name, id, url, and project name.

**Definition**: `azureDevops.pipelines()`

**Examples**

You could write a Scorecard rule to ensure that the entity has at least 1 pipeline that scans vulnerabilities:

```
azureDevops.pipelines().any(pipeline => pipeline.name.matchesIn("Vuln scan"))
```

You could write a Scorecard rule to ensure that the entity has an Azure DevOps pipeline set:

```
azureDevops.pipelines() != null
```

</details>

<details>

<summary>Pipeline build success rate</summary>

Percentage of build pipelines that complete successfully.

This is calculated against builds on the default branch for commits in the last 30 days: `# successful builds / (# successful + # failed)`.

**Definition:** `git.percentBuildSuccess()`

**Examples**

This expression can be used in a development maturity Scorecard to write a rule making sure at least 95% of build runs are successful:

```
git.percentBuildSuccess() >= 0.95
```

</details>

<details>

<summary>Pipeline metrics</summary>

List pipelines with metrics. Metrics contains the successRate & averageDuration of a pipeline.

**Definition**: `azureDevops.pipelineMetrics()`

**Examples**

You could write a Scorecard rule to ensure pipelines have a successRate higher than 95%:

```
azureDevops.pipelineMetrics().all((pipeline) => pipeline.metrics.successRate > 0.95)
```

</details>

<details>

<summary>Pipeline runs</summary>

Get pipelines runs meeting the given filter criteria, which includes results, states. Results include "succeeded", "failed", "canceled", "unknown", states include "completed", "inProgress", "canceling", "unknown".

**Definition**: `azureDevops.pipelineRuns()`

**Examples**

List pipeline runs that are opened and reviewed within 1 day:

```
azureDevops.pipelineRuns().filter(run => run.run.completedDate != null).map((run) => run.run.createdDate.until(run.run.completedDate)).averageDuration() < duration("P1D")
```

</details>

<details>

<summary>Recency of last commit</summary>

Calculates the duration of time between Scorecard evaluation and the date of the last commit from the entity's Git repository.

**Definition:** `git.lastCommit().freshness`

**Examples**

One of the first rules you might write for a Scorecard focused on development maturity or security is one validating that the last commit was within the last month:

```
git.lastCommit().freshness < duration("P1M")
```

As counterintuitive as it may seem, services that are committed too infrequently are actually at more risk. People who are familiar with the service may leave a team, institutional knowledge accumulates, and from a technical standpoint, the service may be running outdated versions of your platform tooling.

</details>

<details>

<summary>Reviews</summary>

List reviews left during a defined lookback period.

* Organization
* Repository
* Review date
* Reviewer

**Definition:** `git.reviews()`

**Examples**

A development maturity Scorecard might use the `git.reviews()` expression to make sure that there is a rigorous review process in place before changes are implemented:

```
git.reviews(lookback=duration("P7D")).length > 25
```

This rule makes sure that there are more than 25 reviews left in the last week.

</details>

<details>

<summary>Search repository files</summary>

Find all instances of code search query from within a repository.

Can filter by path, file name (extension required in file name), or extension. Filters can use \* for glob matching. Supplying a query is required.

**Definition:** `git.codeSearch((query = <query: Text>) (, path = <path: Text>) (, fileName = <fileName: Text>) (, fileExtension = <fileExtension: Text>)): List<GitSearchResult>`

**Examples**

You can use the `git.codeSearch()` expression to query for entities that have certain components, like icons:

```
git.codeSearch(query = "icon", fileExtension = "css").length > 0
```

</details>

<details>

<summary>Top repository language</summary>

Find top used language for a repository, if available.

**Definition:** `git.topLanguage()`

**Examples**

Let's say the primary language developers should be using is Kotlin. You can write a rule to make sure that the top language associated with entities is Kotlin:

```
git.topLanguage() == "kotlin"
```

You can also use this expression to query for entities that don't have Kotlin as the top language to identify those that need to be updated:

```
git.topLanguage() != "kotlin"
```

</details>

<details>

<summary>Work items</summary>

Number of **unresolved** work items associated with the entity, where unresolved is defined as the WIQL \[System.State] NOT IN ('Closed', 'Done', 'Completed', 'Inactive', 'Removed').

**Definition:** `azureDevops.workItems()`

**Examples**

For a Scorecard measuring entity maturity, you can use this expression to make sure entities have fewer than 10 Azure DevOps work items:

```
azureDevops.workItems().length <= 10
```

</details>

<details>

<summary>Work items from WIQL query</summary>

Number of work items associated with the entity based on arbitrary WIQL query.

**Definition:** `azureDevops.workItems(query: Text | Null)`

**Examples**

For a more specific rule in an entity maturity Scorecard, you can use this expression with a WIQL query to make sure entities have no more than 3 tickets with "Doing" status and highest priority.

```
jira.workItems("System.State = \"Doing\" AND Microsoft.VSTS.Common.Priority = 1").length <= 3
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex conducts a background sync of Azure DevOps identities every day at 10 a.m. UTC. Pull requests and work items are refreshed every 5 minutes.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Azure Resources

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Azure Resources](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/overview) provides on-demand cloud computing platforms and APIs. Cortex uses the Azure Resource API to pull in resource details and import entities such as SQL servers, virtual machines, virtual networks, load balancers, and others.

Integrating Azure Resources with Cortex allows you to:

* [Automatically import entities](#enable-automatic-discovery-of-azure-resource-entities) and track ownership of entities
* Create [Scorecards](#scorecards-and-cql) to drive alignment and track progress on projects involving resources from Azure

## How to configure Azure Resources with Cortex

### Prerequisites

Before getting started, you will need the following information. These can be found in the **Enterprise applications** section of Azure:

* Azure tenant ID
* Azure client ID and [client secret](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app#add-credentials)
* Azure subscription ID
  * Ensure that the service principal for the subscription ID has a [Reader role](https://learn.microsoft.com/en-us/entra/identity-platform/howto-create-service-principal-portal#assign-a-role-to-the-application).

### Configure the integration in Cortex

1. In Cortex, navigate to the [Azure Resources settings page](https://app.getcortexapp.com/admin/integrations/azureresources).
   * Click **Integrations** from the main nav. Search for and select **Azure Resources**.
2. Click **Add configuration**.
3. Configure the Azure Resources integration form:
   * **Account alias**: Enter your Azure account alias. Account aliases are used to tie service registrations to different configuration accounts.
   * **Azure tenant ID**: Enter your Azure tenant ID.
   * **Client ID** and **Client secret**: Enter your Azure client ID and secret.
   * **Subscription ID**: Enter your Azure subscription ID.
4. Click **Save**.
   * You will be redirected to the Azure Resources Settings page in Cortex, where you can optionally choose to include only specified Azure resource types for this integration. You can also enable [automatic import](#enable-automatic-discovery-of-azure-resource-entities) for any discovered entities of known types.

After saving your configuration, you are redirected to the integration settings page in Cortex. In the upper right corner of the page, click **Test configuration** to ensure Azure Resources was configured properly.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex Entities to Azure Resources

{% hint style="info" %}
For Azure Resources, Cortex replaces non-alphanumeric characters in entity names with a space. For example, `resource_1` would become `resource 1`.

For the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag), Cortex replaces non-alphanumeric characters with `-` and lowercases the letters. If multiple special characters appear together in a tag, Cortex replaces the group of characters with only one `-`. For example, `mY_e%ntity#$_tag` would become `my-e-ntity-tag`.
{% endhint %}

### Enable automatic discovery of Azure Resource entities

You can configure automatic import from Azure:

1. In Cortex, navigate to the [Entities Settings page](https://app.getcortexapp.com/admin/settings/entities).
2. Next to **Auto import from AWS, Azure, and/or Google Cloud**, click the toggle to enable the import.\\

   <figure><img src="/files/p4fNmdV0qFSbUMX1YwGD" alt=""><figcaption></figcaption></figure>

### Discover ownership for Azure Resources

Cortex can automatically discover ownership for your Azure resources. To configure this:

* Make sure that your Azure resources have a tag matching the `x-cortex-tag` of the corresponding Cortex team
* Enable the “Sync ownership from Azure” toggle in the [Azure Resources Settings page](https://app.getcortexapp.com/admin/settings/azureresources) in Cortex.
  * By default, Cortex looks for the `owner` tag. You can also customize the tag key name on the Settings page.

Cortex syncs ownership from Azure Resources every day at 6 a.m. UTC.

### Define a dependency

Cortex automatically discovers dependencies between your services and resources by scanning for resources with specific Azure Resources tags. By default, a service will have dependencies on any Cortex resource that has a corresponding Azure Resources resource with Azure Resources tag key = "service" and tag value = the service's Cortex tag.

On the [Azure Resources settings page](https://app.getcortexapp.com/admin/settings/azureresources), you can customize the tag key names for dependencies.

For more information on defining dependencies, please see the [Dependencies documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/dependencies).

### Import entities from Azure Resources

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on importing entities.

### Editing the entity descriptor

You can associate a Cortex entity with one or more Azure Resources entities. Cortex will display those Azure Resources entities' metadata on the Cortex entity page.

When the entity is connected to Azure, the entity YAML will look like the following:

```yaml
x-cortex-azure:
  ids:
  - id: /subscriptions/1fbb2da1-2ce7-45e4-b85f-676ab8e685b9/resourceGroups/GROUP1/providers/Microsoft.Compute/disks/vm1_disk1_3d9f85717666435e9e87e4883d31a7e9
    alias: my-default-alias # alias is optional and only relevant if you have opted into multi account support
  - id: /subscriptions/1fbb2da1-2ce8-45e4-b85f-676ab8e685b0/resourceGroups/GROUP2/providers/Microsoft.Compute/disks/vm1_disk1_3d9f85717666435e9e87e4883d31a7e0
    alias: my-other-alias # alias is optional and only relevant if you have opted into multi account support
```

## Using the Azure Resources integrations

### Scorecards and CQL

With the Azure Resources integration, you can create Scorecard rules and write CQL queries based on Azure Resources details.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Get Azure Resource details for entity</summary>

Get Azure Resource details for an entity.

**Definition:** `azureResource.details(): Object`

**Examples**

In a Scorecard, you can write a rule to make sure an entity has Azure Resource details:

```
azureResource.details() != null
```

Make sure an entity has an environment tag:

```
azureResource.details().resources.filter((resource) => jq(resource, ".metadata.\"environment\"") != null).length > 0
```

Make sure an entity has a health check:

```
jq(azureResource.details(), ".resources[].metadata.siteConfig.healthCheckPath") != null
```

Make sure an entity has a tag with a certain key and value:

```
azureResource.details().resources.filter((resource) => resource.tags.get("tag-key") == "tag-value").length > 0
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex conducts a background sync of Azure Resources every day at 00:00 a.m. UTC and an ownership sync every day at 6 a.m. UTC.

## FAQs and troubleshooting

**Why is the Azure resource type `microsoft-resources-subscriptions-resourcegroups` not pulling in Azure Resource details?**

Cortex pulls from the Azure Resource API, but not from the Azure Resource Group API. If you would like to submit a feature request for support of Azure Resource Groups, please contact our customer engineering team.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# BambooHR

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

## Overview

[BambooHR](https://www.bamboohr.com/) is a Human Resources Information System (HRIS) solution that allows you to define organizational membership. Integrate Cortex with BambooHR to automatically sync team memberships, giving you insight into entity ownership.

## How to configure BambooHR with Cortex

### Prerequisite

Before getting started, create a [BambooHR API key](https://documentation.bamboohr.com/docs#section-authentication).

### Configure the integration in Cortex

1. In Cortex, navigate to the [BambooHR settings page](https://app.getcortexapp.com/admin/integrations/bamboohr).
   * Click **Integrations** from the main nav. Search for and select **BambooHR**.
2. Click **Add configuration**.
3. Configure the BambooHR integration form:
   * **Subdomain**: Enter your BambooHR subdomain.
     * This can be found in your app URL, e.g., `subdomain.bamboohr.com`.
   * **API token**: Enter your BambooHR API token.
   * **Report ID**: Optionally, enter a Report ID to filter the list of employees.
     * We recommend entering a Report ID if you have a custom BambooHR Report that has the authoritative list of active employees.
     * This value can be found in the app URL, e.g., `subdomain.bamboohr.comreports/custom/New+Hires/REPORTID`
   * **Employee ownership field**: Optionally, enter the ownership field name.
     * If left blank, Cortex defaults to finding the list of employees using their `division` followed by their `department`.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to BambooHR

### Import entities from BambooHR

See the [Create teams documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams#creating-a-team) for instructions on importing entities.

### Editing the entity descriptor

Ownership of each catalog entity through BambooHR is defined through an owner of type `group`.

```yaml
x-cortex-owners:
  - type: group
    name: My Bamboo HR Team
    provider: BAMBOO_HR
    description: This is a description for this owner # optional
```

The `name` should be exactly equal to the [value in the Team field](#team-field).

## Using the BambooHR integration

### Scorecards and CQL

With the BambooHR integration, you can create Scorecard rules and write CQL queries based on BambooHR teams.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>All ownership details</summary>

A special built-in type that supports a null check or a count check, used to enforce ownership of entities.

**Definition:** `ownership: Ownership | Null`

**Example**

An initial level in a security Scorecard might include a rule to ensure an entity has at least one team as an owner:

```
ownership.teams().length > 0
```

</details>

<details>

<summary>All owner details</summary>

List of owners, including team members and individual users, for each entity

**Definition:** `ownership.allOwners()`

**Example**

The Scorecard might include a rule to ensure that entity owners all have an email set:

```
ownership.allOwners().all((member) => member.email != null)
```

</details>

<details>

<summary>Team details</summary>

List of teams for each entity

**Definition:** `ownership.teams(): List<Team>`

**Example**

The Scorecard might include a rule to ensure that an entity owners all have a description and are not archived:

```
ownership.teams().all(team => team.description != null and team.isArchived == false)
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex conducts an ownership sync for BambooHR teams every day at 6 a.m. UTC.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Bitbucket

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Bitbucket](https://bitbucket.org/product/) is a Git-based version control system from Atlassian. You can use Bitbucket to drive insights into repository details in the Catalog and Scorecard rules.

Integrating Bitbucket with Cortex allows you to:

* Discover and track ownership of Bitbucket entities
* [View Bitbucket data on entity pages](#view-bitbucket-information-on-entity-pages-in-cortex) in Cortex
* Follow a [GitOps](/configure/gitops) workflow with Bitbucket
* View information about pull requests in the [engineering homepage](#engineering-homepage)
* Use Bitbucket metrics in [Eng Intelligence](#eng-intelligence) to understand key metrics and gain insight into services, incident response, and more
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your Bitbucket repositories

{% hint style="info" %}
Bitbucket data in [Eng Intelligence](#eng-intelligence) and in the [engineering homepage](#dev-homepage) is available in private beta. Please contact your Cortex Customer Success Manager for access.
{% endhint %}

## How to configure Bitbucket with Cortex

There are multiple options for integrating with Bitbucket:

* Cloud: Using a workspace token (recommended), the Cortex Atlassian app, or an app password.
* On-prem: Using Basic auth or using OAuth
* You can also integrate using Cortex Axon Relay, a relay broker that allows you to securely connect your on-premises Bitbucket data.

See the tabs below for instructions on the method you choose.

{% tabs %}
{% tab title="Workspace token" %}
**Configure Cortex with Bitbucket using a workspace token**

**Step 1: Generate a workspace token in Bitbucket**

1. In Bitbucket, navigate to **Settings > Workspace settings > Access tokens**.
2. Create a workspace-level access token. Include the following scopes:
   1. `Repositories: Read`
   2. `Pull requests: Read`

**Step 2: Configure the integration in Cortex**

1. In Cortex, navigate to the [Bitbucket settings page](https://app.getcortexapp.com/admin/integrations/bitbucket).
   * Click **Integrations** from the main nav. Search for and select **Bitbucket**.
2. For the configuration type, select **Cloud (workspace token)**.\
   ![](/files/fBpwWgXGCYJY5y4CLTxA)
3. Configure the form:
   * **Account alias**: Enter an alias for the account. Aliases are used to tie service registrations to different configuration accounts.
   * **Token**: Enter the workspace token you generated in Bitbucket.
4. Click **Save**.

**Step 3: Set your Bitbucket workspace**

1. On the [Bitbucket Settings page](https://app.getcortexapp.com/admin/settings/bitbucket) in Cortex, next to your integration's alias, click **Add workspace**.\
   ![Click on Add workspace](/files/hxFsB4EpyluMoTf0yU0h)
2. In the "Workspace configuration" modal, enter your Workspace name.
   * You can find this in Bitbucket under **Settings > Workspace settings**.
3. Click **Save**.
   {% endtab %}

{% tab title="Atlassian app" %}
**Configure Cortex with Bitbucket using the Atlassian app**

**Step 1: Install the Cortex Atlassian app**

Follow the [installation instructions in the Atlassian Marketplace](https://marketplace.atlassian.com/apps/1225295/cortex?tab=installation\&hosting=cloud) for the Cortex app.

**Step 2: Configure the integration in Cortex**

1. In Cortex, navigate to the [Bitbucket settings page](https://app.getcortexapp.com/admin/integrations/bitbucket).
   * Click **Integrations** from the main nav. Search for and select **Bitbucket**.
2. Click **Add Bitbucket configuration**.
3. For the configuration type, select select **Atlassian app**.

   <div align="left"><figure><img src="/files/fBpwWgXGCYJY5y4CLTxA" alt="" width="270"><figcaption></figcaption></figure></div>
4. Configure the "Add Bitbucket configuration" form:
   * **Account alias**: Enter an alias for the account. Aliases are used to tie service registrations to different configuration accounts.
5. Click **Save**.
   * You will be redirected to the Bitbucket Settings page in Cortex.

**Step 3: Connect to Atlassian from Cortex**

1. On the [Bitbucket settings page](https://app.getcortexapp.com/admin/settings/bitbucket) in Cortex, click **Atlassian Application**. ![Click on Atlassian Application](/files/ywxTAZI7C5HRvUTp4ncd)
2. In the popup that appears, click **Grant access** to authorize Cortex access to your Atlassian Workspace.
   {% endtab %}

{% tab title="App password" %}
**Configure Cortex with Bitbucket using an app password**

{% hint style="warning" %}
Bitbucket is [deprecating app passwords on June 9, 2026](https://www.atlassian.com/blog/bitbucket/bitbucket-cloud-transitions-to-api-tokens-enhancing-security-with-app-password-deprecation). If you are currently using an app password, we recommend switching to a workspace token or the Atlassian app before that date.
{% endhint %}

**Step 1: Create an app password**

* Follow Atlassian's documentation to [create an app password for Bitbucket](https://support.atlassian.com/bitbucket-cloud/docs/create-an-app-password/).
  * Make sure to give the app password the following minimum permissions: `Repositories: Admin`, `Repositories: Read`, `Pull requests: Read`

**Step 2: Configure the integration in Cortex**

1. In Cortex, navigate to the [Bitbucket settings page](https://app.getcortexapp.com/admin/integrations/bitbucket).
   * Click **Integrations** from the main nav. Search for and select **Bitbucket**.
2. Click **Add configuration**.
3. For the configuration type, select **Cloud (basic auth)**.

   <div align="left"><figure><img src="/files/fBpwWgXGCYJY5y4CLTxA" alt="" width="270"><figcaption></figcaption></figure></div>
4. Configure the "Add Bitbucket configuration" form:
   * **Account alias**: Enter an alias for the account. Aliases are used to tie service registrations to different configuration accounts.
   * **Username**: Enter your Bitbucket username.
     * You can find this in Bitbucket under **Personal settings > Account settings > Bitbucket profile settings**.
   * **Password**: Enter the app password you created in the previous steps.
5. Click **Save**.
   * You will be redirected to the Bitbucket Settings page.

**Step 3: Set your Bitbucket workspace**

1. On the [Bitbucket Settings page](https://app.getcortexapp.com/admin/settings/bitbucket) in Cortex, next to your integration's alias, click **Add workspace**.\
   ![Click on Add workspace](/files/hxFsB4EpyluMoTf0yU0h)
2. In the "Workspace configuration" modal, enter your Workspace name.
   * You can find this in Bitbucket under **Settings > Workspace settings**.
3. Click **Save**.
   {% endtab %}

{% tab title="Basic" %}
**Configure Cortex with Bitbucket using a on-premises basic auth**

{% hint style="warning" %}
Bitbucket is [deprecating app passwords on June 9, 2026](https://www.atlassian.com/blog/bitbucket/bitbucket-cloud-transitions-to-api-tokens-enhancing-security-with-app-password-deprecation). If you are currently using an app password for basic auth, we recommend switching to an alternative authentication method before that date.
{% endhint %}

**Step 1: Create an app password**

* Follow Atlassian's documentation to [create an app password for Bitbucket](https://support.atlassian.com/bitbucket-cloud/docs/create-an-app-password/).
  * Make sure to give the app password the following minimum permissions: `Repositories: Admin`, `Repositories: Read`, `Pull requests: Read`

**Step 2: Configure the integration in Cortex**

1. In Cortex, navigate to the [Bitbucket settings page](https://app.getcortexapp.com/admin/integrations/bitbucket).
   * Click **Integrations** from the main nav. Search for and select **Bitbucket**.
2. Click **Add configuration**.
3. For the configuration type, select **On-prem (basic auth)**.

   <div align="left"><figure><img src="/files/fBpwWgXGCYJY5y4CLTxA" alt="" width="270"><figcaption></figcaption></figure></div>
4. Configure the "Add Bitbucket configuration" form:
   * **Account alias**: Enter an alias for the account. Aliases are used to tie service registrations to different configuration accounts.
   * **Host**: Enter your Bitbucket on-prem host, e.g., `https://bitbucket.example.com`.
   * **Username**: Enter your Bitbucket username.
     * You can find this in Bitbucket under **Personal settings > Account settings > Bitbucket profile settings**.
   * **Password**: Enter the app password you created in the previous steps.
5. Click **Save**.

Note: When using an on-premises configuration of Bitbucket, the language does not populate on [entity detail pages](#view-bitbucket-information-on-entity-pages-in-cortex).
{% endtab %}

{% tab title="OAuth" %}
**Configure Cortex with Bitbucket on-premises using OAuth**

{% hint style="info" %}
Scaffolder and Workflow automation are supported with this configuration. See [Registering a Scaffolder template](/streamline/workflows/scaffolder) for setup details.
{% endhint %}

**Prerequisites**

To configure this integration with on-prem OAuth, you must be running a self-hosted Bitbucket instance with Bitbucket Server or Data Center version 7.20 or higher.

**Step 1: Set up an application link in Bitbucket**

1. In your Bitbucket server, navigate to **Settings > System > Application Links > Create Link**.
2. Configure the application link:
   * For the application type, select "External Application."
   * For the direction, select "Incoming."
   * For the redirect URL:
     * Default configuration: Enter the URL of your Cortex instance and `/oauth/internal/bitbucket`.
     * Non-default configuration: Enter the URL of your Cortex instance and `/oauth/internal/bitbucket/{alias}`.
   * For the Permission, select `Projects: Admin` and `Repositories: Admin`.
3. Click **Save**.
4. Copy the client ID and client secret. You will need these in the next steps.

**Step 2: Configure the integration in Cortex**

1. In Cortex, navigate to the [Bitbucket settings page](https://app.getcortexapp.com/admin/integrations/bitbucket).
   * Click **Integrations** from the main nav. Search for and select **Bitbucket**.
2. Click **Add configuration**.
3. For the configuration type, select **On-prem (OAuth)**.

   <div align="left"><figure><img src="/files/fBpwWgXGCYJY5y4CLTxA" alt="" width="270"><figcaption></figcaption></figure></div>
4. Configure the "Add Bitbucket configuration" form:
   * **Account alias**: Enter an alias for the account. Aliases are used to tie service registrations to different configuration accounts.
   * **Host**: Enter your Bitbucket on-prem host, e.g., `https://bitbucket.example.com`.
   * **Client ID**: Enter the client ID you obtained in the previous steps.
   * **Client secret**: Enter the client secret you obtained in the previous steps.
5. Click **Save**.

Note: When using an on-premises configuration of Bitbucket, the language does not populate on [entity detail pages](#view-bitbucket-information-on-entity-pages-in-cortex).
{% endtab %}

{% tab title="Relay" %}
**Configure Bitbucket with Cortex Axon Relay**

{% hint style="info" %}
Scaffolder and Workflow automation are supported when connecting Bitbucket via Axon Relay. See [Registering a Scaffolder template](https://docs.cortex.io/streamline/workflows/scaffolder) for setup details.
{% endhint %}

See [Internally hosted integrations](/ingesting-data-into-cortex/integrations/axon-relay) for instructions. Make sure to follow the Bitbucket-specific instructions for the docker-compose.yml file.
{% endtab %}
{% endtabs %}

Once you save your configuration, you'll see it listed on the integration's settings page in Cortex. If you’ve set everything up correctly, you’ll see the option to **Remove Integration** in Settings.

You can also use the **Test all configurations** button to confirm that the configuration was successful. If your configuration is valid, you’ll see a banner that says “Configuration is valid. If you see issues, please see documentation or reach out to Cortex support.”

**Configure the integration for multiple Bitbucket accounts**[**​**](https://docs.cortex.io/docs/reference/integrations/bitbucket#configure-the-integration-for-multiple-propsintegration-accounts)

The Bitbucket integration has multi-account support. You can add a configuration for each additional by repeating the process above.

Each configuration requires an alias, which Cortex uses to correlate the designated with registrations for various entities. Registrations can also use a default configuration without a listed alias. You can edit aliases and default configurations from the Bitbucket page in your Cortex settings. Select the edit icon next to a given configuration and toggle **Set as default** on. If you only have one configuration, it will automatically be set as the default.

Cortex supports mapping multiple identities for a single user if you have multiple configurations of Bitbucket. See the [Identity mapping](/configure/settings/managing-users/identity-mapping) documentation for more information.

### Limit which Bitbucket projects are used for the integration

If you are a part of multiple projects in Bitbucket but you only want to show repositories for a specific set of projects, you can specify the projects in Cortex:

1. Navigate to the [Bitbucket integration settings page](https://app.getcortexapp.com/admin/settings/bitbucket).
2. Click the pencil icon in the row containing the Bitbucket configuration you want to edit.\\

   <figure><img src="/files/LWbZ1zGMmhrbua9qi6wE" alt="Click the pencil icon to edit the Bitbucket configuration."><figcaption></figcaption></figure>
3. Under **Project names**, select which projects you want to include.\
   ![](/files/MiclIIF1e57JvjA9TxcD)
4. At the bottom of the side panel, click **Save**.

### Use webhooks for GitOps functionality

To use webhooks for GitOps functionality, you need to set a secret token on the [Bitbucket Settings](https://app.getcortexapp.com/admin/settings/bitbucket) page. This helps Cortex identify that the webhook event is valid. Make sure to enter the same secret when configuring the webhook on Bitbucket Server. \\

<figure><img src="/files/LyLOPNZ0Co1bB6V8A6pp" alt=""><figcaption></figcaption></figure>

## How to connect Cortex entities to Bitbucket

### Import entities from Bitbucket

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on importing entities.

### Editing the entity descriptor

**Set repository details**

By specifying the `x-cortex-git` field in your Cortex entity descriptor, you'll be able to see Git information in the entity page, including the top language, recent commits, and top contributors.

```yaml
x-cortex-git:
  bitbucket:
    repository: /
    basepath: myService # optional
    alias: myApp # optional
```

| Field        | Description                                                                                        | Required |
| ------------ | -------------------------------------------------------------------------------------------------- | -------- |
| `repository` | `org/repo` as defined in Bitbucket                                                                 | true     |
| `basepath`   | If the entity is in a monorepo (e.g. in a subdirectory), use this field to define the subdirectory | false    |
| `alias`      | Alias is optional and only relevant if you have opted into multi account support                   | false    |

The value for `repository` should be the *workspace/repo* as defined in Bitbucket.

**Ownership**

You can define the following block in your Cortex entity descriptor to add your Bitbucket teams.

```yaml
x-cortex-owners:
  - type: group
    name: Team Name
    provider: BITBUCKET
    description: This is a description for this Bitbucket team that owns this entity.
```

| Field         | Description                                                    | Required |
| ------------- | -------------------------------------------------------------- | :------: |
| `type`        | Ownership type; must be defined as `group` for Bitbucket teams |   **✓**  |
| `name`        | Bitbucket team name                                            |   **✓**  |
| `provider`    | Name of integration (in this case, `BITBUCKET`)                |   **✓**  |
| `description` | Description for the Bitbucket team                             |          |

### Identity mappings

Cortex maps users' email addresses to discovered Bitbucket accounts, so you never need to define email ownership in an entity descriptor.

You can confirm users' Bitbucket accounts are connected from [Bitbucket identity mappings in settings](/configure/settings/managing-users/identity-mapping).

## Using the Bitbucket integration

### View Bitbucket information on entity pages in Cortex

The Bitbucket integration populates the **Repository** block on an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details). For cloud configurations, it also populates the **Language** block. If a Bitbucket team has been defined as the owner for an entity, it will also appear in the Owners block.

<figure><img src="/files/vYrbvmisuYqlr0ElwDqE" alt=""><figcaption></figcaption></figure>

In the **Recent activity** preview, you'll find the recent commits and releases.

#### **Events**

On an entity's **Events** page, you can find all of the commits and releases associated with that entity. Each is hyperlinked to the commit or release page in Bitbucket and includes a timestamp.

#### **CI/CD**

To see pipeline runs for Bitbucket, use the [deploys API](/ingesting-data-into-cortex/entities-overview/entities/deploys) to add deploy information. After doing this, from the **CI/CD > Deploys** page in the entity's sidebar, you will see a history of pipeline runs.

#### **Workflows**

If a Workflow applies to a given entity, any actions you can perform are available under the **Workflows** link in the side panel of an entity.

#### **Repository**

You can access more detailed information pulled from Bitbucket in the **Repository** link in the sidebar. At the top of the repository page, see the repositories associated with that entity. For cloud configurations, you can also see the most-used language in files for that entity. In the **Top contributors** block, you'll find the three users who have contributed the most code and the number of their contributions.

In the **Commits** section, you'll find the 10 most recent commits and metadata about each. Below **Commits** is the **Recent releases** section, which includes the 5 most recent releases.

#### **Packages**

Packages are automatically scraped from your Git repos or they can be submitted via the [packages API](/api/readme/packages). The package file must be in the root of your repository — or, if you're using `basepath`, in the root of the subdirectory — to be scraped by Cortex. You can query an entity's packages in [CQL explorer](https://app.getcortexapp.com/admin/cql-explorer) using `packages()`.

To view packages, click **Packages** in the entity's sidebar.

The following package types are automatically scraped from repositories:

* JavaScript / Node.js: `package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`
* Python: `requirements.txt`, `pipfile.lock`
* .NET (C#): `packages.lock.json`
* Java: `pom.xml`
* Go: `go.sum`

All other files of these types can be added via the [packages API](/api/readme/packages).

### Engineering homepage

{% hint style="info" %}
Bitbucket in the homepage is available in private beta. Please contact your Cortex Customer Success Manager for access.

Note: Because of rate limits, Bitbucket ingestion in the homepage is limited to repositories that are mapped to an entity in Cortex.
{% endhint %}

The Bitbucket integration enables Cortex to pull information about pull requests and work items into the [homepage](/streamline/homepage). You can find your open pull requests and any pull requests assigned to you for review.

Pull requests from Bitbucket are refreshed every 5 minutes.

### Eng Intelligence

{% hint style="info" %}
Bitbucket in Eng Intelligence is available in private beta. Please contact your Cortex Customer Success Manager for access.\
\
Note: Because of rate limits, Bitbucket ingestion in Eng Intelligence is limited to repositories that are mapped to an entity in Cortex.
{% endhint %}

The [Eng Intelligence tool](/improve/eng-intelligence) also uses pull request data from Bitbucket to generate metrics:

* Average PR open to close time
* Avg time to first review
* Avg time to approval
* PRs opened
* Weekly PRs merged
* Avg PRs reviewed/week

You can read more about how Eng Intelligence tracks metrics for teams and users in the Eng Intelligence walkthrough.

### Scorecards and CQL

With the Bitbucket integration, you can create Scorecard rules and write CQL queries based on Bitbucket details.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Approvals required to merge</summary>

The total number of approvals required to merge a Pull Request into the repository, defaulting to 0 if no approvals are defined.

**Definition:** `git.numOfRequiredApprovals(): Number`

**Example**

In a Scorecard, you can write a rule to encourage at least one approval for each Pull Request:

```
git.numOfRequiredApprovals() >= 1
```

</details>

<details>

<summary>Git repository set</summary>

Check if an entity has a registered Git repository.

**Definition:** `git (==/!=) null: Boolean`

**Example**

In a Scorecard, you can write a rule that detects whether an entity has a Git repository set:

```
git != null
```

</details>

<details>

<summary>Pipeline build success rate</summary>

The percentage of build pipelines that complete successfully. This is calculated against builds on the default branch, for commits in the last 30 days. The calculation is # successful builds / (# successful + # failed). **Definition:** `git.percentBuildSuccess(): Number`

**Example**

In a Scorecard, you can write a rule that requires at least 90% of build runs to be successful:

```
git.percentBuildSuccess() > 0.9
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex conducts a background sync of Bitbucket identities every day at 10 a.m. UTC. Repositories are refreshed every day at 2 p.m. UTC.

## Troubleshooting and FAQ

**Rules are failing saying that I don't have file `x`, but I verified that the file exists.**

We always use the default branch for file existence checks. Make sure that the file is present in the default branch.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# BugSnag

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[BugSnag](https://www.bugsnag.com/) is an application stability monitoring platform that provides error tracking and analytics.

Integrating BugSnag with Cortex allows you to:

* [View errors on entity pages](#viewing-bugsnag-errors-on-an-entity) in Cortex, giving you insight into your entity's operational maturity
* Create [Scorecards](#scorecards-and-cql) that include rules related to BugSnag errors

## How to configure BugSnag with Cortex

### Prerequisites

Before getting started:

* Create a [BugSnag auth token](https://bugsnagapiv2.docs.apiary.io/#introduction/authentication) in your [BugSnag account's settings page](https://app.bugsnag.com/settings/my-account) under "My account."
* You must have the `Configure integrations` permission in Cortex.

{% hint style="warning" %}
If you're using a self-hosted instance of BugSnag, you'll need to verify that your Cortex instance is able to reach the BugSnag instance.\
\
We route our requests through a static IP address. Reach out to support at <help@cortex.io> to receive details about our static IP. If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your BugSnag instance.
{% endhint %}

### Configure the integration in Cortex

1. In Cortex, navigate to the [BugSnag settings page](https://app.getcortexapp.com/admin/integrations/bugsnag).
   * Click **Integrations** from the main nav. Search for and select **BugSnag**.
2. Click **Add configuration**.
3. Configure the integration form:
   * **Auth token**: Enter the auth token you generated in BugSnag.
   * **Organization slug**: Enter your BugSnag organization slug.
     * You can find this in your BugSnag URL, e.g., `https://app.bugsnag.com/organizations/{SLUG}/stability-center`.
   * **Host**: If using a custom BugSnag instance, enter the URL here *without* the API path (e.g., `bugsnag.getcortexapp.com`).
4. Click **Save**.

After saving your configuration, you are redirected to the BugSnag integration settings page in Cortex. In the upper right corner of the page, click **Test configuration** to ensure BugSnag was configured properly.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to BugSnag projects

### Discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) as the "best guess" for BugSnag projects. For example, if your Cortex tag is `my-entity`, then the corresponding project in BugSnag should also be `my-entity`.

If your BugSnag projects don’t cleanly match the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag), you can override this in the Cortex entity descriptor.

### Editing the entity descriptor

You can define projects under the `x-cortex-bugsnag` block:

```yaml
x-cortex-bugsnag:
  project: my-project
```

| Field     | Description                    | Required |
| --------- | ------------------------------ | :------: |
| `project` | Project key defined in BugSnag |   **✓**  |

## Using the BugSnag integration

### Viewing BugSnag errors on an entity

Error data will appear on an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details). You can find the total number of detected errors and a full list on the **Error tracking** page in the entity's side panel. Error data is fetched live.

Each error in the list will display with an `Error`, `Info`, or `Warning` tag based on the [severity](https://docs.bugsnag.com/product/severity-indicator/#severity) applied to a given error in BugSnag.

### Scorecards and CQL

With the BugSnag integration, you can create Scorecard rules and write CQL queries based on BugSnag projects and issues.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if BugSnag is set</summary>

Check if an entity has a registered BugSnag project.

**Definition:** `bugsnag (==/!=) null`

**Example**

This expression can be used to write a Scorecard rule to make sure each entity has a registered BugSnag project:

```
bugsnag != null
```

This is also a good way to double-check that the integration is synced and reporting frequently.

</details>

<details>

<summary>Number of issues</summary>

Count all unresolved issues in BugSnag or counts number of issues for a given query. By default, will count all unresolved issues.

**Definition:** `bugsnag.numOfIssues(query: Text | Null)`

**Example**

For a Scorecard focused on operational maturity, you can pull in error data from BugSnag to make sure your entities have no or few errors.

```
bugsnag.numOfIssues() < 2
```

To set a more specific standard, you can also create a rule based on a [filter](https://docs.bugsnag.com/product/custom-filters/).

```
bugsnag.numOfIssues("filters[error.status][][type]=example")
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Buildkite

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Buildkite](https://buildkite.com/) is a continuous integration and delivery platform that enablers users to run fast, secure, and scalable pipelines on their own infrastructure.

Integrating Buildkite with Cortex allows you to:

* Pull in metrics about your builds and pipelines
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your Buildkite pipelines

## How to configure Buildkite with Cortex

### Prerequisites

Before getting started:

* Create a [Buildkite API access token](https://buildkite.com/docs/apis/managing-api-tokens) with read-only permissions for pipelines and builds.
  * You must be a member of a Buildkite organization to generate and use an access token for it.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Buildkite settings page](https://app.getcortexapp.com/admin/integrations/buildkite).
   * Click **Integrations** from the main nav. Search for and select **Buildkite**.
2. Configure the Buildkite integration form:
   * **API token**: Enter your Buildkite API token.
   * **Organizational slug**: Enter the slug for your Buildkite organization.
     * This can be found in your organization's Buildkite settings, or at the end of your Buildkite URL after navigating to **Pipelines**.
3. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Buildkite

### Discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) for your Buildkite pipeline. For example, if your Cortex tag is `my-pipeline`, then the corresponding pipeline tag in Buildkite should also be `my-pipeline`.

Cortex will also use the the GitHub, GitLab, Bitbucket, or Azure DevOps repository to connect entities to Buildkite pipelines. For example, if the GitHub repo associated with your Buildkite pipeline is `my-org/repo`, then entities in Cortex that also live in `my-org/repo` will populate with details from that pipeline.

### Editing the entity descriptor

You can add Buildkite pipelines to an entity by defining the pipeline slug or tags with one of the following blocks in the entity descriptor:

```yaml
x-cortex-ci-cd:
  buildkite:
    pipelines:
    - slug: my-buildkite-pipeline-slug-1
    - slug: my-buildkite-pipeline-slug-2
```

| Field  | Description                     | Required |
| ------ | ------------------------------- | :------: |
| `slug` | Slug for the Buildkite pipeline |   **✓**  |

```yaml
x-cortex-ci-cd:
  buildkite:
    tags:
    - tag: my-buildkite-tag-1
    - tag: my-buildkite-tag-2
```

| Field | Description                    | Required |
| ----- | ------------------------------ | :------: |
| `tag` | Tag for the Buildkite pipeline |   **✓**  |

The slug for your pipeline can be found in the Buildkite URL for a given pipeline (e.g., `https://buildkite.com//`).

## Using the Buildkite integration

#### Entity pages

Once the Buildkite integration is established, Cortex will automatically pull in pipeline data to an entity's page. You can access this data from the **CI/CD** page in the entity's side panel.

You can find a list of pipeline runs for each pipeline linked to a given entity on this page:

* Pipeline slug/tag
* Action (e.g. "scheduled build")
* Timestamp
* Branch
* State

The [state](https://buildkite.com/docs/pipelines/notifications#build-states) for a build will appear as a tag next to the pipeline slug/tag (e.g. `canceled`, `passed`, or `failed`).

### Scorecards and CQL

With the Buildkite integration, you can create Scorecard rules and write CQL queries based on Buildkite pipelines.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Buildkite pipeline(s) are set</summary>

Check if entity has registered Buildkite pipelines in its entity descriptor.

**Definition:** `buildkite (==/!=) null`

**Example**

For a Scorecard focused on production readiness, you can pull in data from Buildkite to make sure that entities belong to a CI/CD pipeline.

```
buildkite != null
```

</details>

<details>

<summary>Get Buildkite build(s)</summary>

Gets pipelines and builds that meet given filter criteria.

* Build criteria:
  * Branch
  * Commit
  * Created at
  * ID
  * Message
  * Number
  * Pipeline
  * State
* Pipeline criteria:
  * Description
  * Git repository
  * ID
  * Name
  * Slug
  * Tags

States include CANCELED, PASSED, and FAILED.

**Definition**: `buildkite.builds()`

**Example**

If you're building a Scorecard with an emphasis on operational maturity, you could set a rule to make sure not only that entities belong to a pipeline, but that the pipeline is functioning as expected.

```
buildkite.builds(states["passed"]).length >=1
```

</details>

<details>

<summary>Get Buildkite pipelines</summary>

Get all Buildkite pipelines associated with the entity: Description, Git repository, ID, Name, Slug, Tags.

**Definition**: `buildkite.pipelines()`

**Example**

A production readiness Scorecard can use this expression in a rule confirming that there are pipelines linked to a specific repository:

```
buildkite.pipelines().any((pipeline) => pipeline.gitRepository = )
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Checkmarx

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

## Overview

Checkmarx is an automated application security platform that checks source code for security vulnerabilities and compliance issues. Integrate Cortex with Checkmarx to drive insight into the vulnerabilities detected on your entities.

This integration is supported for [Checkmarx Static Application Security Testing (SAST)](https://checkmarx.com/cxsast-source-code-scanning/).

## How to configure Checkmarx with Cortex

### Prerequisites

Before getting started, create a user with access to the `sast_rest_api` scope.

{% hint style="warning" %}
If you're using a self-hosted instance of Checkmarx, you'll need to verify that your Cortex instance is able to reach the Checkmarx instance.\
\
We route our requests through a static IP address. Reach out to support at <help@cortex.io> to receive details about our static IP. If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your Checkmarx instance.
{% endhint %}

### Configure the integration in Cortex

1. In Cortex, navigate to the [Checkmarx settings page](https://app.getcortexapp.com/admin/integrations/checkmarx).
   * Click **Integrations** from the main nav. Search for and select **Checkmarx**.
2. Click **Add configuration**.
3. Configure the Checkmarx integration form:
   * **Username** and **Password**: Enter the username and password for the user with access to `sast_rest_api`.
   * **Host**: Enter the full URL of your Checkmarx instance.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Checkmarx

### Discovery

By default, Cortex will use your associated Git repository (e.g. `repo-name`) or the service tag as the "best guess" for the Checkmarx project name.

If your repository and entity names don’t cleanly match the Checkmarx CxSAST project names, or if you have multiple Checkmarx projects for a service, you can add a Checkmarx project ID (recommended) or a Checkmarx project name in the Cortex entity descriptor.

### Editing the entity descriptor

We recommend using the project ID as it is a unique identifier across projects.

Example using project IDs:

```yaml
x-cortex-checkmarx:
  projects:
    - projectId: 1234
    - projectId: 2345
```

Example using both project IDs and names:

```yaml
x-cortex-checkmarx:
  projects:
    - projectName: My Cool Project
    - projectId: 1234
```

## Using the Checkmarx integration

#### Entity pages

Once the integration is established, vulnerabilities pulled from Checkmarx will be available for each entity in the **Code and Security** block in the **Overview** tab.

While viewing an entity, click **Code & security > Checkmarx**. On this page, view the number of vulnerabilities per severity and a link directly to your Checkmarx instance.

### Scorecards and CQL

With the Checkmarx integration, you can create Scorecard rules and write CQL queries based on Checkmarx details.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Checkmarx project is set</summary>

Check if entity has a registered Checkmarx project in its entity descriptor. If there is a Checkmarx project name, we will try and make sure that the project exists in Checkmarx.

**Definition:** `checkmarx (==/!=) null: Boolean`

**Example**

In a Scorecard, you can write a rule to check whether an entity has a Checkmarx project set:

```
checkmarx != null
```

</details>

<details>

<summary>Checkmarx scan risk</summary>

Get the maximum scan risk among the entity's project's latest scans

**Definition:** `checkmarx.sastScanRisk(): Number`

**Example**

In a Scorecard, you can write a rule to verify that an entity has no Checkmarx projects where the latest scan risk is higher than 35:

```
checkmarx.sastScanRisk() < 35
```

</details>

<details>

<summary>Number of Checkmarx vulnerabilities</summary>

Get the count of all vulnerabilities for an entity's Checkmarx project's last scan

**Definition:** `checkmarx.numOfVulnerabilities(): Number`

**Example**

In a Scorecard, you can write a rule to verify that an entity has no vulnerabilities with a severity of `HIGH`:

```
checkmarx.numOfVulnerabilities(severity=["High"]) < 1
```

Verify that an entity has less than 5 vulnerabilities total:

```
checkmarx.numOfVulnerabilities() < 5
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## FAQs and troubleshooting

**Does Cortex support integrating with Checkmarx One?**

No, Cortex does not currently support Checkmarx one. Only Checkmarx SAST is supported for this integration.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# CircleCI

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[CircleCI](https://circleci.com/) is continuous integration and continuous delivery platform that can be used to implement DevOps best practices.

Integrating CircleCI with Cortex allows you to:

* [View information about CircleCI workflows and pipelines on entity pages](#viewing-circleci-information-on-entity-pages) in Cortex
* Create [Scorecards](/standardize/scorecards) that track progress and drive alignment on projects involving your CircleCI data

## How to configure CircleCI with Cortex

### Prerequisites

Before getting started:

* Create a [CircleCI API token](https://circleci.com/docs/managing-api-tokens/).

**Self-hosted CircleCI instances**

If you’re using a self-hosted instance of CircleCI, you’ll need to verify that your Cortex instance is able to reach the CircleCI instance.\
\
We route our requests through a static IP address. Reach out to support at <help@cortex.io> to receive details about our static IP. If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your CircleCI instance.

### Configure the integration in Cortex

1. In Cortex, navigate to the [CircleCI settings page](https://app.getcortexapp.com/admin/integrations/circleci).
   * Click **Integrations** from the main nav. Search for and select **CircleCI**.
2. Click **Add configuration**.
3. Configure the integration form:
   * **Account alias**: Enter an alias for this integration, used to tie entity registrations to different configurations.
   * **API token**: Enter the value of the API token you created in CircleCI.
   * **Host**: Enter the URL for your CircleCI instance if self-hosted, e.g., `https://cortex.circleci.com`
4. Click **Save**.

**Configure the integration for multiple CircleCI accounts**[**​**](https://docs.cortex.io/docs/reference/integrations/circleci#configure-the-integration-for-multiple-propsintegration-accounts)

The CircleCI integration has multi-account support. You can add a configuration for each additional by repeating the process above.

Each configuration requires an alias, which Cortex uses to correlate the designated with registrations for various entities. Registrations can also use a default configuration without a listed alias. You can edit aliases and default configurations from the CircleCI page in your Cortex settings. Select the edit icon next to a given configuration and toggle **Set as default** on. If you only have one configuration, it will automatically be set as the default.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to CircleCI

### Editing the entity descriptor

You can define CircleCI projects in an [entity's YAML descriptor](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file). Add its project slug under the `x-cortex-circle-ci` block:

```yaml
x-cortex-circle-ci:
  projects:
    - projectSlug: circleci-projectslug # projectslug in CircleCI
      alias: circleci-alias # alias is optional and only relevant if you have opted into multi account support
```

## Using the CircleCI integration

### Viewing CircleCI information on entity pages

When an entity has a CircleCI project defined in its YAML file, you will see metric and pipeline details on an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details). Click **CI/CD > CircleCI** in the entity's sidebar to see this information.

### Scorecards and CQL

With the CircleCI integration, you can create Scorecard rules and write CQL queries based on CircleCI metrics and pipelines.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check for CircleCI flaky tests</summary>

Get all Circle CI flaky tests associated with the entity.

**Definition**: `circleci.flakyTests()`

**Example**

You could create a Scorecard with a rule that verifies no flaky tests:

```
circleci.flakyTests().length == 0
```

</details>

<details>

<summary>Get Circle CI projects</summary>

Get all Circle CI projects associated with the entity.

**Definition**: `circleci.projects()`

**Example**

You could also create a rule that checks for a success rate over 90%:

```
circleci.projects().all((project) => project.metrics.successRate > 0.9) == true
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# ClickUp

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[ClickUp](https://clickup.com/) is a project management tool that combines tasks, document collaboration, and issue management in a single platform.

Integrating ClickUp with Cortex allows you to:

* View task information directly on [entity pages](#entity-pages) in Cortex
* Create ClickUp tasks based on Initiatives directly from Cortex
* Map ClickUp identities to users in Cortex
* View open ClickUp tasks in the [dev homepage](#dev-homepage)
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your ClickUp tasks

## How to configure ClickUp with Cortex

### Prerequisites

Before getting started:

* Create a [ClickUp personal API token](https://clickup.com/api/developer-portal/authentication/#generate-your-personal-api-token).

### Configure the integration in Cortex

1. In Cortex, navigate to the [ClickUp settings page](https://app.getcortexapp.com/admin/integrations/clickup).
   * Click **Integrations** from the main nav. Search for and select **ClickUp**.
2. Click **Add configuration**.
3. Configure the ClickUp integration form:
   * **API token**: Enter your ClickUp API token.
4. Click **Save**.

If you’ve set everything up correctly, you’ll see the option to **Remove Integration** in settings.

You can also use the **Test configuration** button to confirm that the configuration was successful. If your configuration is valid, you’ll see a banner that says “Configuration is valid. If you see issues, please see documentation or reach out to Cortex support.”

Note that mapping options will not appear in Cortex for users who have not finished user registration in ClickUp. If a user is partially registered, Cortex will filter them out of the mapping page.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to ClickUp

### Auto discovery of spaces, folders, and tags

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) as the "best guess" for ClickUp space, folder, or tag. For example, if your Cortex tag is `my-entity`, then the corresponding space, folder, or tag in ClickUp should also be `my-entity`.

If your ClickUp space, folder, or tag don’t cleanly match the Cortex tag, you can override this in the Cortex entity descriptor.

### Editing the entity descriptor

You can map any number of ClickUp spaces, folders, and tags to a Cortex entity. Spaces and folders can be mapped by using either ID or name.

You can find your folder ID or space ID in your ClickUp URL: `https://app.clickup.com/:workspace_id/v/f/:folder_id/:space_id`.

**Mapping spaces by ID or name**

When mapping spaces, you can use the ID or name for the space.

```yaml
x-cortex-issues:
  clickup:
    spaces:
      - identifier: 123456789
        identifierType: ID
```

```yaml
x-cortex-issues:
  clickup:
    spaces:
      - identifier: My Space
        identifierType: NAME
```

These blocks share the same fields:

| Field            | Description                                            | Required |
| ---------------- | ------------------------------------------------------ | :------: |
| `spaces`         | Denotes that mapping should be based on ClickUp spaces | **true** |
| `identifier`     | Identifier for the space; either the full ID or name   | **true** |
| `identifierType` | Type of identifier; either `ID` or `NAME`              | **true** |

**Mapping folders by ID or name**

When mapping folders, you can use the ID or name for the folder.

```yaml
x-cortex-issues:
  clickup:
    folders:
      - identifier: 123456789
        identifierType: ID
```

```yaml
x-cortex-issues:
  clickup:
    folders:
      - identifier: my-folder
        identifierType: NAME
```

| Field            | Description                                            | Required |
| ---------------- | ------------------------------------------------------ | :------: |
| `folders`        | Denotes that mapping should be based on ClickUp folder | **true** |
| `identifier`     | Identifier for the folder; either the full ID or name  | **true** |
| `identifierType` | Type of identifier; either `ID` or `NAME`              | **true** |

**Mapping by tags**

Cortex also supports mapping entities to ClickUp [tags](https://help.clickup.com/hc/en-us/articles/6304382595991-Manage-task-tags).

```yaml
x-cortex-issues:
  clickup:
    tags:
      - name: tag a
      - name: tag b
      - name: tag c
```

| Field     | Description                                          | Required |
| --------- | ---------------------------------------------------- | :------: |
| `folders` | Denotes that mapping should be based on ClickUp tags | **true** |
| `name`    | Name for the tag                                     | **true** |

### Specify a list for Initiative issues

You can also specify a ClickUp list to store all issues created via Cortex Initiatives. If `Use list defined in entity YAML` is **toggled on** in the Initiative issue creation form, Cortex will automatically create tasks in the specified list for a given entity.

If a list is not specified in an entity's YAML and `Use list defined in entity YAML` option is **toggled on** in the initiative issue creation form, Cortex will attempt to create a list in the mapped space or folder above.

Define one of these following blocks in an entity descriptor to specify a list for Initiative issues.

**Specify list by ID**

```yaml
x-cortex-issues:
    clickup:
      initiativesList:
        id: 12345
```

| Field             | Description         | Required |
| ----------------- | ------------------- | :------: |
| `initiativesList` | Denotes that Cortex | **true** |
| `name`            | Name for the tag    | **true** |

**Specify list by name**

```yaml
x-cortex-issues:
    clickup:
      initiativesList:
        name: Cortex Initiative Issues
```

### Identity mappings

Cortex maps email addresses in your ClickUp instance to email addresses that belong to team members in Cortex. When [identity mapping](/configure/settings/managing-users/identity-mapping) is set up, users will be able to see their personal on-call status from the developer homepage.

Note that mapping options will not appear in Cortex for users who have not finished user registration in ClickUp. If a user is partially registered, Cortex will filter them out of the mapping page.

## Using the ClickUp integration

### Entity pages

**Integrations - ClickUp**

Tasks detected from your ClickUp instance will populate on the **Issue tracking** page in the entity's sidebar. Each row will show the following information (when available in ClickUp):

* Task name (hyperlinked to task in ClickUp)
* Project
* Assignees
* Priority
* Created at
* Due date

### Initiatives

Initiatives allow you to set deadlines for specific rules or a set of rules in a given Scorecard and send notifications to users about upcoming due dates.

From the Issues tab of an Initiative, you can automatically [create a ClickUp task from a failing rule](#create-a-task-from-an-initiative-issue).

### Dev homepage

The ClickUp integration enables Cortex to pull information about tasks into the Dev homepage. You can find open tasks assigned to you under the [Issues tab](https://app.getcortexapp.com/admin/home?activeTab=Issues).

Issues are refreshed every 5 minutes, or you can click **Refresh ClickUp tasks** to manually refresh issues.

### Scorecards and CQL

With the ClickUp integration, you can create Scorecard rules and write CQL queries based on ClickUp tasks.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>List of ClickUp tasks</summary>

Get ClickUp tasks meeting the given filter criteria.

* Assignees
* Created at
* Creator
* Due date
* Folder
* Priority
  * "Urgent", "High", "Normal," and "Low"
* Status
* Tags
* Task name

Statuses are dependent on your own ClickUp configured statuses. Closed tasks are filtered out by default.

**Definition:** `clickup.tasks()`

**Examples**

To evaluate the maturity of an entity in a Scorecard, you can use this expression to make sure it has fewer than five unassigned ClickUp tasks:

```
clickup.tasks().filter((task) => task.assignees.length < 1).length < 5
```

You can also query for entities that don't have any urgent ClickUp tasks with a "security" tag:

```
clickup.tasks(priorities=["Urgent"], tags=["security"]).length == 0
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Create a task from an Initiative issue

Initiatives allow you to set deadlines for specific rules or a set of rules in a given Scorecard and send notifications to users about upcoming due dates. You can create a ClickUp task from a failing rule in an Initiative. Learn more in [Creating issues based on Initiatives](/improve/initiatives/issue-config).

The issue configuration will apply to all entities that meet the filter criteria. Once an entity is passing the rule, Cortex will automatically close the associated ticket.

## Background sync

Cortex conducts a background sync of ClickUp identities every day at 10 a.m. UTC. Pull requests and issues are refreshed every 5 minutes.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Codecov

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Codecov](https://about.codecov.io/) is a code coverage reporting platform that that monitors how much of your code has been tested and validated. Codecov analytics can be used to drive visibility into your microservice architecture and understand coverage trends over time.

Integrating Cortex with Codecov allows you to:

* View code coverage details for entities directly in Cortex
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your Codecov code coverage metrics

## How to configure Codecov with Cortex

### Prerequisites

Before getting started:

* Create a [Codecov access token](https://docs.codecov.io/reference#usagen).

### Configure the integration in Cortex

1. In Cortex, navigate to the [Codecov settings page](https://app.getcortexapp.com/admin/integrations/codecov).
   * Click **Integrations** from the main nav. Search for and select **Codecov**.
2. Click **Add configuration**.
3. Configure the Codecov integration form:
   * **API token**: Enter your Codecov access token.
   * **Host**: If you're using a custom Codecov instance, enter your host URL.
     * Make sure to enter the URL **without** the API path (e.g., `https://codecov.getcortexapp.com`).
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Codecov

### Auto discovery of Codecov projects

Cortex will use the GitHub, GitLab, Bitbucket, or Azure DevOps repository as the "best guess" for the corresponding Codecov project, since Codecov projects are connected to repositories. For example, if the GitHub repo associated with your Codecov instance is `my-org/repo`, then the entities in Cortex should also be associated with `my-org/repo`.

You can find the repository for a given entity in its YAML, defined in a block like the one below:

```yaml
x-cortex-git:
  github:
    repository: cortexapps/sample-repo
```

If the Codecov project you want to associate isn't the same as the repository, you can override this in the Cortex entity descriptor.

{% hint style="warning" %}
While Cortex uses the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) for discovery with many integrations, the **repository** is used for Codecov projects.
{% endhint %}

### Editing the entity descriptor

```yaml
x-cortex-static-analysis:
  codecov:
    owner: org-name
    repo: my-project
    provider: AZURE_DEVOPS | BITBUCKET | BITBUCKET_SERVER | GITHUB | GITHUB_ENTERPRISE | GITLAB | GITLAB_ENTERPRISE
    flag: flag
```

| Field      | Description                                          | Required |
| ---------- | ---------------------------------------------------- | :------: |
| `owner`    | Name of the Git organization                         |   **✓**  |
| `repo`     | Git repository (without the organization)            |   **✓**  |
| `provider` | One of the Git providers in the sample YAML          |   **✓**  |
| `flag`     | Pulls from isolated and categorized coverage reports |          |

The value for `repo` should be the **full repository** because Codecov maps projects by repo.

**Flags**

Codecov's [flags](https://docs.codecov.com/docs/flags) are used to categorize coverage reports for various features and tests in a given project. Flags allow you to set different statistics for different areas of your code base. For example, if you have a monorepo with multiple unique projects, you can use Codecov flags to evaluate each project with different test coverage metrics.

To pull flags into Cortex, define the `flag` line in the [entity descriptor block](#editing-the-entity-descriptor).

{% hint style="warning" %}
If you choose to configure with flags, discovery will be disabled; you would need to define the `owner`, `repo`, and `provider` lines.
{% endhint %}

## Using the Codecov integration

#### Entity pages

With the Codecov integration, you can find code coverage details on an entity's details page as long as that entity is associated with a repo linked to your Codecov instance.

Click **Code & security** in the entity's sidebar to see the code coverage for that entity.

### Scorecards and CQL

With the Codecov integration, you can create Scorecard rules and write CQL queries based on Codecov code coverage metrics.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Code coverage</summary>

Code coverage for an entity's Git repository (out of 100)

**Definition:** `codecov.codeCoverage()`

**Example**

For a Scorecard focused on development maturity, you can set a rule to make sure code coverage for a given entity is at least 95%:

```
codecov.codeCoverage() >= 95
```

Set a threshold that is both challenging and realistic so there's an incentive for developers to improve.

</details>

{% hint style="success" %}
Setting up a rule based on code coverage can serve as a secondary check to confirm an entity is synced with Codecov and reporting frequently.
{% endhint %}

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Coralogix

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

## Overview

[Coralogix](https://coralogix.com/) is an observability and security platform. Integrate Cortex with Coralogix to drive insights into alerts.

After setting up the integration, relevant alerts from Coralogix will appear in your entity pages. While viewing an entity, click **Integrations > Coralogix** in its sidebar to view the list of alerts.

## How to configure Coralogix with Cortex

### Prerequisites

Before getting started, generate a [Coralogix API key](https://coralogix.com/docs/alerts-api/#api-access).

### Step 1: Configure the integration in Cortex

1. In Cortex, navigate to the [Coralogix settings page](https://app.getcortexapp.com/admin/integrations/coralogix)
   * Click **Integrations** from the main nav. Search for and select **Coralogix**.
2. Click **Add configuration**.
3. Configure the Coralogix integration form:
   * **Account alias**: Enter your account alias.
   * **API key**: Enter your Coralogix API key.
   * **Region**: Select your region.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Coralogix

### Discovery

By default, Cortex will use the entity name or [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-service`) as the "best guess" for the Coralogix alert application name. For example, if your entity name is "My Service" and your Cortex tag is “my-service”, then the corresponding application name in Coralogix should be “My Service” or "my-service".

If your Coralogix application names don’t cleanly match the Cortex tag, you can override this in the Cortex entity descriptor.

### Editing the entity descriptor

Coralogix alerts can be listed in the Catalog under the `Coralogix` section. We support application names in the YAML for pulling Coralogix alerts.

```yaml
info:
  x-cortex-coralogix:
    applications:
    - applicationName: my-app # application name tied to alert
      alias: my-alias # alias is optional and only relevant if you have opted into multi account support
```

## Using the Coralogix integration

### Scorecards and CQL

With the Coralogix integration, you can create Scorecard rules and write CQL queries based on Coralogix alerts.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Coralogix application is set</summary>

Check if entity has a registered Coralogix application in its entity descriptor. If no registration exists, we'll try to automatically detect which corresponding Coralogix application is associated with the entity.

**Definition:** `coralogix (==/!=) null: Boolean`

**Example**

You could write a rule that checks whether an entity has a Coralogix application set:

```
coralogix != null
```

</details>

<details>

<summary>Alerts</summary>

List of alerts, filterable on status

**Definition:** `coralogix.alerts(): List`

**Example**

You could write a rule that checks whether an entity has at least 3 alerts:

```
ccoralogix.alerts().length >= 3
```

You could write a rule that checks whether an entity has no alerts and status triggered:

```
coralogix.alerts(statuses = ["triggered"]).length -= 0
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>


# Custom webhook integrations

Custom webhook integrations allow you to POST data to a unique endpoint in Cortex, map the payload to existing entities, and make that data available for use in [Scorecards](/standardize/scorecards), [CQL queries](/standardize/cql), and on [entity detail pages](/ingesting-data-into-cortex/entities-overview/entities/details).

Using a custom webhook is especially helpful if:

* You have internal tools, homegrown systems, or third-party services that Cortex doesn't integrate with yet.
* You want to automate the process of sending custom metrics, events, or other data into Cortex without building and maintaining additional infrastructure.
* You want to pre-process data before it reaches Cortex, such as adding extra metadata or transforming the payload format.

This can be done without auth or an explicit [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) in the URL if you do not have access to the Cortex tag or the ability to add authentication headers.

{% hint style="info" %}
You can also add custom metadata manually to an entity descriptor or programmatically via the API. Learn more in [Adding custom data](/ingesting-data-into-cortex/entities-overview/entities/custom-data).
{% endhint %}

Below the instructions, see an example demonstrating how to [send additional GitHub metadata into Cortex via webhook](#example-github-webhook).

## How to create a custom webhook integration in Cortex

### Step 1: Configure the custom integration in Cortex

1. In Cortex, navigate to **Integrations**. On the left side of the Integrations page, click [**Custom integrations**](https://app.getcortexapp.com/admin/integrations#integration-category-custom).
2. Click **+Add custom integration**.\\

   <figure><img src="/files/8BueJl5ZSioebN3Wx9a1" alt="Click +Add custom integration."><figcaption></figcaption></figure>
3. Configure the integration details:
   * **Integration name**: Enter a name for the integration.
   * **Entity tag JQ**: Enter the JQ that will be used to extract the entity's [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) from the data. This tells Cortex where in the payload body we can find the Cortex tag.
     * For example, the payload shown in [Step 2](#step-2-send-data-to-the-webhook) would have `.data.codeTag` as the JQ, and `frontend-service` would be the entity's Cortex tag.
     * If the tag Cortex extracts from the payload does not match an existing Cortex tag, it will result in a 400 error and the custom metadata will not be updated. Learn about [alternate mappings below](#changing-the-mappings-for-entities).
   * **Key**: Enter the custom metadata key.
     * Data will be stored under the key for entities, similar to adding data via [entity descriptor](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file) or [API](/api/readme/custom-data).
     * In the [example below](#step-2-post-json-with-curl), the key is `mydata`.
4. Click **Save**.
5. Copy the provided webhook URL.

### Step 2: Send data to the webhook

Note that the entity must exist in Cortex before you send the payload.

cURL is a quick and flexible method to post to the webhook and verify that it's receiving data.

1. Save your payload as a .json file. Include the field that matches the JQ expression configured in the previous steps, so Cortex can map the data to the correct entity.\
   For example, the payload might look like this:

```json
{
  "data": {
    "codeTag": "frontend-service",
    "mydata": "4"
  }
}
```

2. In your terminal, use cURL to POST the JSON, using a command similar to the following:\
   `curl -X POST -H "Content-Type: application/json" --data <path to json file> <webhook URL>`
   * For example: `curl -X POST -H "Content-Type: application/json" --data @/tmp/payload.json https://api.getcortexapp.com/api/v1/custom-integrations/data/12345abcdef`

After sending data, the JSON payload is written to the entity's key that you configured for the custom webhook in [Step 1](#step-1-configure-the-custom-integration-in-cortex).

### **Changing the mappings for entities**

If the webhook payload does not contain a value that maps to the exact [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag), you can configure alternative mappings to look up when processing payloads. Use the `x-cortex-custom-integration-mappings` block in the [entity descriptor YAML](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file). For example:

```yaml
x-cortex-custom-integration-mappings:
  - frontend
  - brain-service
```

When processing a payload, Cortex takes the output of the **Entity tag JQ** field in Step 1 above and searches for an entity with that value as a Cortex tag. If no such entity exists, Cortex checks whether an entity has registered the value as an alternative mapping; if so, the payload is attached to that entity.

## View custom integration data in Cortex

Similar to when you [add custom metadata to an entity](/ingesting-data-into-cortex/entities-overview/entities/custom-data), custom integration data appears in the sidebar on an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details) within the **Custom data & metrics** page. It appears with an `INTEGRATION` tag next to the key name.

<figure><img src="/files/aVzQZIqyffyMMYWP3e5R" alt="The &#x22;Custom data and metrics&#x22; page in an entity&#x27;s sidebar displays data from webhook integrations."><figcaption></figcaption></figure>

## Example: GitHub webhook

In this example, we create a webhook integration to send GitHub data into Cortex.

While Cortex does offer a native integration with [GitHub](/ingesting-data-into-cortex/integrations/github), there may be scenarios where you want to send additional metadata that isn't included in the native integration.

1. [Create a custom webhook integration](#step-1-configure-the-custom-integration-in-cortex) in Cortex.
   * Enter a descriptive name so others understand the purpose of this webhook, such as "GitHub metadata."
   * In this example, we use the **Service query** `.repository.name` and the **Key** `githubTest`.
2. Copy the webhook URL generated in Cortex for this integration.
3. In GitHub, under **Settings > Webhooks**, create a webhook.
   * In the webhook's settings under **Payload URL**, paste in the webhook URL from Cortex.
   * Set the **Content type** to `application/json`.
4. Push a commit to your GitHub repository.
   * In your GitHub settings under **Webhooks**, click the **Recent Deliveries** tab to see the payload that will be sent. Because you set the JQ query to `.repository.name`, the repository name value in the payload will correspond with the Cortex tag in Cortex.\
     In the example screen shot, the repository name is "michigan":\\

     <div align="left"><figure><img src="/files/0vS3oC9itnB3gt93zSjO" alt="The repository name appears in the &#x22;Recent deliveries&#x22; tab for the webhook in GitHub." width="563"><figcaption></figcaption></figure></div>
5. Navigate to the entity in Cortex.
   * In this example, the repository name is "michigan," so we can search in Cortex to find an entity with "michigan" as its Cortex tag.
6. On the [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details), click **Custom data & metrics** from the entity's sidebar.
   * Next to the `githubTest` key, you will see the payload sent from GitHub:\\

     <figure><img src="/files/Mnrr15Y0TFbPSlzBZeCj" alt="The custom webhook data appears next to the key on the entity page."><figcaption></figcaption></figure>


# Datadog

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Datadog](https://www.datadoghq.com/) is an application performance monitoring platform that provides real-time observability into entities, servers, databases, and tools, providing developers with a comprehensive understanding of their infrastructure as well as the ability to identify areas for improvement.

Cortex is uniquely equipped to augment Datadog's tools, providing greater visibility into your entities. In this guide, you'll learn how to set up the Datadog integration to pull in services and metrics for entities:

* Monitors
* SLOs
* Dependencies

## How to configure Datadog with Cortex

### Prerequisites

Before getting started, make sure you have created the following:

* [Datadog application key](https://docs.datadoghq.com/account_management/api-app-keys/#application-keys)
  * You can create this in Datadog under **Organizational Settings > Applications Key**.
  * Include the following scopes:
    * `monitors_read`
    * `apm_api_catalog_read`
    * `dashboards_read`
    * `metrics_read`
    * `timeseries_query`
    * `apm_service_catalog_read`
    * `slos_read`
    * `apm_read`
* [Datadog API key](https://docs.datadoghq.com/account_management/api-app-keys/#api-keys)
  * You can create this in Datadog under **Organizational Settings > API Key**.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Datadog settings page](https://app.getcortexapp.com/admin/integrations/datadog).
   * Click **Integrations** from the main nav. Search for and select Datadog.
2. Click **Add configuration**.
3. Configure the Datadog integration form:
   * **Account alias**: Enter a name that Cortex will associate this configuration with.
   * **App key**: Enter the application key you generated in Datadog.
     * This key appears under the **Key** column in Datadog while viewing your list of Application Keys.\\

       <figure><img src="/files/KgS974hwMM9TivrrKvkj" alt=""><figcaption></figcaption></figure>
   * **API key**: Enter the API key you generated in Datadog.
   * **Region**: Select your [Datadog region](https://docs.datadoghq.com/getting_started/site/) from the dropdown.
   * **Custom subdomain**: Enter the custom subdomain for your Datadog instance.
     * This field only takes the subdomain, not the entire URL. For example, this field would take `cortex-docs` from `https://cortex-docs.datadoghq.com`.
   * **Environments**: Optionally, enter environment tags for Datadog entities.
     * If you set an environment tag here, make sure to set the [`env` dropdown in Datadog](https://docs.datadoghq.com/service_catalog/navigating/#performance-view) to match.
4. Click **Save**.

After saving your configuration, you are redirected to the Datadog integration settings page in Cortex. In the upper right corner of the page, click **Test configuration** to ensure Datadog was configured properly.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

#### **Configure the integration for multiple Datadog accounts**[**​**](https://docs.cortex.io/docs/reference/integrations/datadog#configure-the-integration-for-multiple-propsintegration-accounts)

The Datadog integration has multi-account support. You can add a configuration for each additional by repeating the process above.

Each configuration requires an alias, which Cortex uses to correlate the designated with registrations for various entities. Registrations can also use a default configuration without a listed alias. You can edit aliases and default configurations from the Datadog page in your Cortex settings. Select the edit icon next to a given configuration and toggle **Set as default** on. If you only have one configuration, it will automatically be set as the default.How to connect Cortex entities to Datadog

## How to connect Cortex entities to Datadog

### Tag discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) as the "best guess" for Datadog tag. For example, if your Cortex tag is `my-entity`, then the corresponding tag in Datadog should also be `my-entity`.

If your Datadog tags don’t cleanly match the Cortex tag, you can override this in the Cortex entity descriptor.

### Import entities from Datadog

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on importing entities.

### Editing the entity descriptor

You can use service tags to connect Datadog services to Cortex entities.

```yaml
x-cortex-apm:
  datadog:
    serviceTags:
      - tag: entity
        value: brain
        alias: my-default-alias
      - tag: entity
        value: cerebrum
        alias: my-other-alias
```

| Field   | Description                                                                                         | Required |
| ------- | --------------------------------------------------------------------------------------------------- | -------- |
| `tag`   | Tag for the project in Datadog                                                                      | **✓**    |
| `value` | Value for the project; Cortex will find monitors and SLOs by querying `tag:value OR tag:value2 ...` | **✓**    |
| `alias` | Alias for the configuration in Cortex (only needed if you have opted into multi-account support)    |          |

These tags are used to "discover" your monitors and SLOs. Cortex will find monitors and SLOs by querying `tag:value OR tag:value2 ...`

If you want to hard code and/or override discovery, you can define a monitor or SLOs block in the entity descriptor, as described below.

#### **Monitors and SLOs**

Adding monitors let you see information about their current status directly from a catalog - via the Monitors column - and under the `Operations` section of an entity page. You can find your monitors from Datadog's [Manage Monitors page](https://app.datadoghq.com/monitors/manage).

The ID of a monitor is found in the URL when you click on a monitor in your Datadog dashboard i.e., `https://app.datadoghq.com/monitors/****`.

```yaml
info:
  x-cortex-apm:
    datadog: 
      monitors:
        - id: 12345
          alias: my-default-alias
        - id: 67890
          alias: my-other-alias
```

Like monitors, Datadog SLOs can be found in the `Operations` section of an entity page. You can find the SLOs for your instance on Datadog's [SLO status page](https://app.datadoghq.com/slo).

The ID for the SLO can be found in the URL when you click on an SLO in the Datadog dashboard. For example, `https://app.datadoghq.com/slo?slo_id=****&timeframe=7d&tab=status_and_history`.

```yaml
info:
  x-cortex-slos:
    datadog:
      - id: 0b73859a3e2504bf09ad23a161702654
        alias: my-default-alias
      - id: 228499184a9efe34d4e4e9df838c7fa1
        alias: my-other-alias
```

Monitors and SLOs have the same field definitions.

| Field   | Description                                                                                      | Required |
| ------- | ------------------------------------------------------------------------------------------------ | :------: |
| `id`    | Datadog ID for the monitor or SLO                                                                |   **✓**  |
| `alias` | Alias for the configuration in Cortex (only needed if you have opted into multi-account support) |          |

### Dependency mapping

Cortex automatically syncs dependencies from Datadog's [Service Map](https://docs.datadoghq.com/tracing/services/services_map/), using the entity identifier (`x-cortex-tag`) to map entities found in the Service Map.

The relationships Cortex discovers through the integration will feed directly into the [Relationships graph](https://app.getcortexapp.com/admin/graph), so you can easily visualize the connections between your entities.

If you have two entities - for example, `entity-one` and `entity-two` - that have a dependency edge in Datadog's Service Map, both entities should exist in Cortex with the same identifiers ([Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag)).

You can override this by [defining Cortex tags](#editing-the-entity-descriptor) where `tag` = `entity` and `value` = `entity name in Datadog Service Map`.

{% hint style="warning" %}
If the Cortex tag does not exactly match the entity identifier in Datadog, the dependencies will not automatically sync. You can override automatic discovery by defining values in the entity descriptor.
{% endhint %}

You can connect an APM service for dependency mapping in the entity descriptor:

```yaml
x-cortex-apm:
  datadog:
    serviceName: cortex-gateway.gateway
```

## Using the Datadog integration

### View Datadog monitors and SLOs on entity pages

With the Datadog integration, you'll be able to find monitors and SLOs on an entity's home page. High-level information about monitors and SLOs appears in the **Overview** tab.

Click **Monitoring** in the entity's sidebar to see more detailed data about both monitors and SLOS. Both sections display tags for Pass, Fail, Warning, and No Data for each monitor or SLO.

* The **SLOs** column shows each SLO, its target(s), the current value for that entity, its status. and the period of time the SLO is being calculated for. For example, if the time listed is "7 days ago," then the SLO is looking at the time range starting 7 days ago to now\..
* The **Monitors** column shows the title for each monitor, its query (if available), and its status.

Clicking any block with a nonzero value will open a modal with more detailed information. The monitor modals will list all monitors with the applicable status. The SLO modals will also display targets for each SLO that is passing or failing.

### Scorecards and CQL

With the Datadog integration, you can create Scorecard rules and write CQL queries based on Datadog metrics, monitors, and SLOS.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

You can read more about Datadog's [metrics](https://docs.datadoghq.com/metrics/types/) and [custom metrics](https://docs.datadoghq.com/metrics/custom_metrics/) in their docs.

<details>

<summary>Metrics</summary>

[Timeseries data](https://docs.datadoghq.com/api/latest/metrics/#query-timeseries-data-across-multiple-products) from Datadog.

* Metric
* Timestamp

**Definition:** `datadog.metrics(query: Text, lookback: Duration, alias: Text | Null)`

**Example**

You can use the `datadog.metrics()` expression to evaluate the health of your entities in a Scorecard:

```
datadog.metrics(query="system.cpu.usage{service:" + datadog.serviceNames().join(" OR service:") + "}",lookback=duration("P2D")).averageBy((point) => point.metricValue) < 0.10
```

This rule makes sure that a given entity's average CPU usage is less than 10% over the last two days.

</details>

<details>

<summary>Monitors</summary>

Monitors associated with a given entity via ID or tags. You can use these data to check whether an entity has monitors associated with it, or whether an entity has the right types of monitors.

* Created at
* Creator email
* Creator name
* Name
* Overall state
* Query
* Tags
* URL

**Definition:** `datadog.monitors()`

**Example**

For a Scorecard focused on operational maturity, this expression can be used to make sure an entity has at least one Datadog monitor set up:

```
datadog.monitors().length >= 1
```

</details>

<details>

<summary>SLOs</summary>

SLOs associated with a given entity via ID or tags. You can use these data to check whether an entity has SLOs associated with it and if those SLOs are passing.

* History
* ID
* Name
* Operation
* Remaining budget
* SLI value
  * Datum
  * Timeseries
* SLO target
* Source
* Thresholds
  * Name
  * Threshold

**Definition:** `slos()`

**Examples**

For a Scorecard focused on operational maturity, this expression can be used to make sure an entity has associated SLOs in Datadog:

```
slos().length > 0
```

This rule checks that there is at least one SLO is set up. While this rule makes sense in a Scorecard's first level, a rule checking the status of the SLO would make sense in a higher level:

```
slos().all((slo) => slo.passing)
```

Entities will pass this rule if all SLOs associated with it have "passing" status.

</details>

### Discovery audit

Cortex will pull recent changes from your Datadog environment into the [discovered entities list](/ingesting-data-into-cortex/entities-overview/entities/discovery-audit). Here, you can find new entities in Datadog that have not been imported into the catalog - these will have the tag **New APM Resource** - as well as entities in the catalog that no longer exist in Datadog - these will have the tag **APM Resource Not Detected**.

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

The dependency sync runs automatically each day at 12 a.m. UTC, and can be run manually via the [**Sync dependencies** button](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/dependencies#sync-dependencies) in the [Relationship Graph](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph).

## FAQs and troubleshooting

**Can I set a Scorecard rule to monitor Datadog monitors/SLOs based on tags?**

Yes, you can [specify key-value pairs](#entity-descriptor) that allow Cortex to discover your SLOs and monitors, and use these tags in Scorecard rules.

**How does Datadog work with other dependency sources?**

When leveraging multiple dependency sources such as Datadog and a catalog entity's YAML, all the sources would be merged together and Cortex will de-duplicate the dependencies.

For example, if an entity YAML indicates `X → Y` and Datadog indicates `X → Y` and `X → Z`, the entity will display two edges presented as `X → Y` and `X → Z`.


# Dynatrace

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

### Overview

[Dynatrace](https://www.dynatrace.com/) is a monitoring and observability platform. Integrate Dynatrace with Cortex to get insights into application performance, service discovery, SLOs, and dependencies.

## How to configure Dynatrace with Cortex

### Prerequisite

Before getting started, generate an [access token in Dynatrace](https://www.dynatrace.com/support/help/dynatrace-api/basics/dynatrace-api-authentication) with the scopes `Read entities` and `Read SLO`.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Dynatrace settings page](https://app.getcortexapp.com/admin/integrations/dynatrace).
   * Click **Integrations** from the main nav. Search for and select Dynatrace.
2. Click **Add configuration**.
3. Configure the Dynatrace integration form:
   * **Domain**: Enter your [Dynatrace domain](https://www.dynatrace.com/support/help/dynatrace-api/environment-api/entity-v2/get-entities-list) necessary to access your environment, depending on whether you use managed, SaaS, or the Environment ActiveGate version.
   * \**API token*: Enter the access token you generated in Dynatrace.
4. Click **Save**.

If you’ve set everything up correctly, you’ll see the option to **Remove Integration** in settings.

You can also use the **Test configuration** button to confirm that the configuration was successful. If your configuration is valid, you’ll see a banner that says “Configuration is valid. If you see issues, please see documentation or reach out to Cortex support.”

## How to connect Cortex entities to Dynatrace

### Import entities from Dynatrace

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on importing entities.

### Editing the entity Entity descriptor

**Entity ID**

Entities with a type of `"SERVICE"` will be discovered and surfaced. When using the Dynatrace portal, service IDs can be found in the URL of a selected service under the id query param. For example, `https://.live.dynatrace.com/#newservices/serviceOverview;id=`

```yaml
x-cortex-apm:
  dynatrace:
    entityIds:
      - mock-service-id-1
      - mock-service-id-2
```

**Entity name**

You can also match entities based on matching [display names](https://www.dynatrace.com/support/help/dynatrace-api/environment-api/entity-v2/get-entities-list#response-body-objects) with a regular expression, like:

```yaml
x-cortex-apm:
  dynatrace:
    entityNameMatchers:
      - "foo.*"
```

#### Linking SLOs in Cortex

Dynatrace supports service-level objective (SLO) monitoring. You can link these SLOs to your Dynatrace entity in Cortex:

1. In Dynatrace, navigate to the Service-Level Objectives app.
   * On the left sidebar of Dynatrace, click **Search**, then type in `slo` to find the app.
2. On the SLOs page, see the list of SLOs. On the right side of an SLO, click **^** to expand the Details.\
   ![The details button is on the right side of an SLO](/files/16oS9WHFjjgR3g6MjQ2Y)
3. In your browser's URL bar, locate the ID in the URL. Copy the ID and store it in a secure location, as you will need this value in the next steps.
   * The ID is displayed in the URL following `sloexp=`. For example, `https://.apps.dynatrace.com/ui/.../sloexp=&slovis=` ![The SLO ID is in the URL](/files/OrsTEqiiiTcxSDYQXs3M)
   * On the SLOs page, expand the details for each SLO to display the SLO ID in the URL.
4. Open your Cortex home page, then navigate to the service you are configuring.
5. In the upper right corner of the service page, click **Switch to YAML**.
6. Paste in the following text, making sure to replace `slo-id-1` and `slo-id-2` with the SLO IDs you obtained from the Dynatrace URL in the previous steps:

```yaml
x-cortex-slos:
  dynatrace:
    - id: slo-id-1
    - id: slo-id-2
```

7. At the bottom of the page, click **Save**.

After saving, navigate back to your service details page to view the SLO status in the service's Overview tab.

For information on working with SLOs in Dynatrace, see [Dynatrace's documentation](https://docs.dynatrace.com/docs/platform-modules/automations/service-level-objectives/configure-and-monitor-slo).

#### Dependencies

Cortex automatically syncs [dependencies](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/dependencies) from Dynatrace using attributes inherent to each entity.

#### Discovery audit

Cortex will pull recent changes from your Dynatrace instance into the [discovered entities list](/ingesting-data-into-cortex/entities-overview/entities/discovery-audit). Here, you can find new entities in Dynatrace that have not been imported into the catalog - these will have the tag **New APM resource** - as well as entities in the catalog that no longer exist in Dynatrace - these will have the tag **APM resource not detected**.

## Using the Dynatrace integration

#### Entity pages

With the Dynatrace integration, you'll see SLOs on an entity's home page. High-level information about SLOs appears in the **Overview** tab.

Click **Monitoring** in the entity's sidebar to see more detailed data: the SLO name, its target, the current value for that entity, and the period of time the SLO is being calculated for. For example, if the time listed is "7 days ago," then the SLO is looking at the time range starting 7 days ago to now.

#### Relationship graphs

[Dependencies](#dependencies) detected from Dynatrace will appear in [Relationship graphs](https://app.getcortexapp.com/admin/graph).

### Scorecards and CQL

With the Dynatrace integration, you can create Scorecard rules and write CQL queries based on Dynatrace SLOs.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>SLOs</summary>

SLOs associated with a given entity via ID or tags. You can use these data to check whether an entity has SLOs associated with it and if those SLOs are passing.

* History
* ID
* Name
* Operation
* Remaining budget
* SLI value
  * Datum
  * Timeseries
* SLO target
* Source
* Thresholds
  * Name
  * Threshold

**Definition:** `slos()`

**Examples**

For a Scorecard focused on operational maturity, this expression can be used to make sure an entity has associated SLOs in Dynatrace:

```
slos().length > 0
```

This rule checks that there is at least one SLO is set up. While this rule makes sense in a Scorecard's first level, a rule checking the status of the SLO would make sense in a higher level:

```
slos().all((slo) => slo.passing)
```

Entities will pass this rule if all SLOs associated with it have "passing" status.

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex conducts a background sync of Dynatrace entities at 7 a.m. UTC and a dependency sync every day at 12 a.m. UTC. You can [manually sync dependencies](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/dependencies#sync-dependencies) via the Relationship Graph.


# Entra ID

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Microsoft Entra ID](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id), formerly known as Azure Active Directory, is an identity service that provides SSO and authentication.

Integrating Cortex with Entra ID allows you to:

* Automatically discover and track Entra ID teams and team memberships
* Track ownership of entities
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your Entra ID teams

{% hint style="info" %}
For information on configuring Entra ID SSO for logging in to Cortex, see the [Microsoft Entra ID SSO documentation](/configure/settings/managing-users/configuring-sso/entraid).
{% endhint %}

## How to configure Entra ID with Cortex

### Step 1: Register and configure a new Active Directory application

1. Follow Microsoft's documentation to [register a new single tenant Entra ID application](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app?tabs=certificate#register-an-application).
2. In your Entra ID admin center, navigate to your new application, and then to API Permissions. Add the following permissions:
   * Microsoft APIs > Microsoft Graph > Application permissions > User > `User.Read.All`
   * Microsoft APIs > Microsoft Graph > Application permissions > Group > `Group.Read.All`
3. Click **Grant Admin Consent** to grant permissions for all accounts in the directory.
4. Navigate to **Certificates & secrets** and click **New client secret**.
   * Note that you will need to rotate the secret before the expiration date you set for it.
5. Navigate to the application's Overview page and copy the client ID. You will need the client ID and secret in the next steps.

### Step 2: Configure the integration in Cortex

1. In Cortex, navigate to the [Entra ID settings page](https://app.getcortexapp.com/admin/integrations/microsoft-entra-id).
   * Click **Integrations** from the main nav. Search for and select **Entra ID**.
2. Click **Add configuration**.
3. Configure the integration form:
   * **Tenant ID**: Enter your Entra ID [tenant ID](https://learn.microsoft.com/en-us/entra/fundamentals/how-to-find-tenant#find-tenant-id-through-the-azure-portal).
   * **Client ID** and **Client secret**: Enter the client ID and secret you generated in the previous steps.
4. Click **Save**.
   * You will be redirected to the Azure Active Directory settings page in Cortex, where you can optionally set a group filter to limit which groups are pulled in from Entra ID.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Entra ID

### Import entities from Entra ID

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on importing entities.

### Editing the entity descriptor

```yaml
x-cortex-owners:
  - type: group
    name: Engineering # group name in Entra ID
    provider: ACTIVE_DIRECTORY
```

The group name is case-sensitive and should be exactly the same as in Entra ID.

## Using the Entra ID integration

### Teams page

Under **Catalogs > Teams**, you will see teams and team members pulled in from Entra ID.

### Entity pages

If you have ownership of entities set up, then Azure AD teams and users will be listed in the **Owners** page for an entity.

### Scorecards and CQL

With the Entra ID integration, you can create Scorecard rules and write CQL queries based on Entra ID teams.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>All ownership details</summary>

A special built-in type that supports a null check or a count check, used to enforce ownership of entities.

**Definition:** `ownership: Ownership | Null`

**Example**

An initial level in a security Scorecard might include a rule to ensure an entity has at least one team as an owner:

```
ownership.teams().length > 0
```

</details>

<details>

<summary>All owner details</summary>

List of owners, including team members and individual users, for each entity

**Definition:** `ownership.allOwners()`

**Example**

The Scorecard might include a rule to ensure that entity owners all have an email set:

```
ownership.allOwners().all((member) => member.email != null)
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex conducts an ownership sync every day at 6 a.m. UTC.

## FAQ and Troubleshooting

**Why were all my Entra ID users unexpectedly deleted after rotating my client secret?**

Updating your configuration can cause a temporary deletion of users. When you delete the old secret from your Azure AD configuration in Cortex, a sync is triggered to delete the users. The addition of the new secret to your configuration will trigger a sync to add the users. There may be a delay before seeing the users re-added.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# FireHydrant

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[FireHydrant](https://firehydrant.com/) is an incident management platform that emphasizes reliability and consistency across the entire incident response lifecycle.

Integrating FireHydrant with Cortex allows you to:

* [View incidents on entity pages](#viewing-firehydrant-incidents-on-an-entity) in Cortex, giving you insight into incidents to act on them quickly
* [Trigger new incidents](#trigger-an-incident) directly from Cortex
* Create [Scorecards](#scorecards-and-cql) to set standards around incident management and production readiness

## How to integrate FireHydrant with Cortex

### Prerequisites

Before getting started:

* Create a [FireHydrant API key](https://app.firehydrant.io/settings/api_keys).

### Configure the integration in Cortex

1. In Cortex, navigate to the [FireHydrant settings page](https://app.getcortexapp.com/admin/integrations/firehydrant):
   * Click **Integrations** from the main nav. Search for and select **FireHydrant**.
2. Click **Add configuration**.
3. Configure the integration:
   * **API key**: Enter the API key you created in FireHydrant.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to FireHyrant projects

### Editing the entity descriptor

You can define FireHydrant services in an [entity's YAML file](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file).

For a given entity, define FireHydrant services by ID or slug. Each of these has the same field definitions.

| Field            | Description                         | Required |
| ---------------- | ----------------------------------- | :------: |
| `identifier`     | Service ID or slug                  |   **✓**  |
| `identifierType` | Type of identifier (`ID` or `SLUG`) |   **✓**  |

```yaml
x-cortex-firehydrant:
  services:
    - identifier: ASDF1234
      identifierType: ID
```

You can find the service ID value in FireHydrant under **FireHydrant > Catalog > Services**. The URL for the service will also contain the ID (e.g., `https://app.firehydrant.io/catalog/services/{ID}/incidents`).

If you prefer to use the service slug in the registration instead, you can find it on the right-hand side of the service page in FireHydrant.

```yaml
x-cortex-firehydrant:
  services:
    - identifier: service-slug
      identifierType: SLUG
```

## Using the FireHydrant integration

### Viewing FireHydrant incidents on an entity

When active incidents are detected in FireHydrant, Cortex will display incident information on an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details).

Click **On-call & incidents** in the entity's sidebar to see all detected incidents.

Each issue will be listed with its title and description (when available). Cortex will also display the status for an issue as a badge next to its name:

* `Acknowledged`
* `Closed`
* `Detected`
* `Identified`
* `Investigating`
* `Mitigated`
* `Postmortem completed`
* `Postmortem started`
* `Resolved`
* `Started`

The issue's severity will also appear in a badge (e.g. `SEV0`, `SEV1`, `SEV2`).

### **Trigger an incident**

While viewing an entity in Cortex, you can trigger an incident in FireHydrant:

1. In Cortex, navigate to an entity. On the left side of an entity details page, click **On-call & incidents.**
2. In the upper right side of the entity's "On-call" page, click **Trigger incident**.
3. Configure the incident modal:
   * **Summary**: Enter a title for the incident.
   * **Description**: Enter a description of the incident.
   * **Severity**: Select a severity level.
   * **Condition:** Nature of the incident - `Unavailable`, `Partially Unavailable`, `Degraded`, `Bug`, or `Operational`.
4. At the bottom of the modal, click **Trigger incident**.
   * A confirmation screen will appear. In the confirmation, click the link to view the incident in FireHydrant.

### Scorecards and CQL

With the FireHydrant integration, you can create Scorecard rules and write CQL queries based on FireHydrant incidents.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if FireHydrant service is set</summary>

Check if entity has a registered FireHydrant service in its entity descriptor. If no registration exists, we'll try to automatically detect which corresponding FireHydrant service is associated with the entity.

**Definition:** `firehydrant (==/!=) null`

**Example**

For a Scorecard focused an production readiness, you can use this expression to make sure a FireHydrant service - and thus incident response - is defined for entities:

```
firehydrant != null
```

This is also a good way to make sure over time that FireHydrant is set up properly and reporting frequently.

</details>

<details>

<summary>Incidents</summary>

List of incidents, filterable on severity and status.

* Created at
* Description
* Impact condition name
* Name
* Severity
* Status

**Definition:** `firehydrant.incidents()`

**Examples**

For a Scorecard focused on service maturity or quality, you can use this expression to make sure there are no detected or identified FireHydrant incidents with a severity rating of 1 for a given entity:

```
firehydrant.incidents(severity = ["SEV1"], statuses = ["Detected", "Identified"]).length == 0
```

You can also tier severity-based rules to indicate progress over time. While the above rule might make sense in the first or second level, a higher-severity rule might make sense in a higher level:

```
firehydrant.incidents(severity = ["SEV3"], statuses = ["Detected", "Identified"]).length == 0
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# GitHub

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[GitHub](https://github.com/) is a Git-based source code repository. You can use GitHub to share code with team members, track and manage changes to code over time, and collaborate on projects across your organization.

Integrating GitHub with Cortex allows you to:

* Automatically discover and track ownership of GitHub entities
* Follow a GitOps workflow with GitHub to manage your Cortex workspace
* View information about your GitHub repositories on an [entity's details page](#expected-results), including: The repo associated with the entity, recent commits and releases in the event timeline, the most-used language in the files for that entity, the top code contributors, and their number of contributions.
  * In an entity's **Code & Security** section, see vulnerabilities from [GitHub Advanced Security](https://docs.github.com/en/get-started/learning-about-github/about-github-advanced-security) (Code scanning, Dependabot alerts, CodeQL, and Secret scanning)
* View information about pull requests and work items in the [engineering homepage](#engineering-homepage)
* Use GitHub metrics in [Eng Intelligence](/improve/eng-intelligence) to understand key metrics and gain insight into services, incident response, and more
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your repositories

You can also optionally integrate GitHub Copilot with Cortex to:

* Track Copilot adoption and impact within [Eng Intelligence](/improve/eng-intelligence)

{% hint style="info" %}
**GitHub Copilot integration**

If you installed the GitHub app prior to October 14, 2025, you must accept new permissions in order to access Copilot metrics in Cortex. [See this KB article](https://support.getcortexapp.com/hc/en-us/articles/41736643663387-Why-is-Cortex-requesting-that-I-re-authorize-the-GitHub-app-for-Copilot-metric-permissions) for more information.
{% endhint %}

## How to configure GitHub with Cortex

### Prerequisites

If you connect Cortex via a [custom GitHub app](#custom-app), it must be configured with a [fine-grained personal access](https://docs.github.com/en/rest/authentication/permissions-required-for-fine-grained-personal-access-tokens) token containing the minimum permissions listed below.

Note: The [Cortex GitHub app](#cortex-github-app) is preconfigured with these permissions.

#### Repository permissions

| **Permission**             |            **Requirement**           | **Purpose(s) in Cortex**                                                                                                                                                                                        |
| -------------------------- | :----------------------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Actions**                |            `Read & write`            | <ul><li>Read workflow run information for Git-based CQL rules</li><li>Artifact information for actions</li></ul>                                                                                                |
| **Administration**         |            `Read & write`            | <ul><li>Create repositories</li></ul>                                                                                                                                                                           |
| **Checks**                 |            `Read & write`            | <ul><li>Used to create and update check runs for linting and validation workflows, such as the cortex.yaml linter on pull requests.</li></ul>                                                                   |
| **Code scanning alerts**   |              `Read-only`             | <ul><li>Get vulnerability information for Git-based CQL rules</li></ul>                                                                                                                                         |
| **Commit statuses**        |            `Read & write`            | <ul><li>Read commits for an entity's Git metadata</li><li>Read commits for Git-based CQL rules</li><li>Show pending status messages on the OpenAPI incompatibility check</li></ul>                              |
| **Contents**               |            `Read & write`            | <ul><li>Read <code>cortex.yaml</code>, <code>cortex-properties.yaml</code>, and package/OpenAPI files</li><li>Read Git rules</li><li>Create file contents</li></ul>                                             |
| **Custom properties**      |            `Read & write`            | <ul><li>Used in <a href="/pages/E4BndAJAkJ3sjXz3SAer">Workflows</a></li></ul>                                                                                                                                   |
| **Dependabot alerts**      |              `Read-only`             | <ul><li>Read vulnerability information for Git CQL rules (only relevant if using Dependabot)</li></ul>                                                                                                          |
| **Deployments**            |            `Read & write`            | <ul><li>Used in <a href="/pages/E4BndAJAkJ3sjXz3SAer">Workflows</a></li></ul>                                                                                                                                   |
| **Issues**                 |            `Read & write`            | <ul><li>Read associated issues with repositories for populating entity Git integration and for Git CQL rules</li><li>Create new issues based on <a href="/pages/tdFcgLBakpb4SUx5Lotc">Initiatives</a></li></ul> |
| **Metadata**               |              `Read-only`             | <ul><li>Read associated data with repositories for populating entity Git integration and for Git CQL rules</li></ul>                                                                                            |
| **Pull requests**          |            `Read & write`            | <ul><li>Read pull request data for Git CQL rules and developer homepage "My PRs" tab</li><li>Comment if there are breaking OpenAPI changes on a PR</li></ul>                                                    |
| **Secret scanning alerts** |              `Read-only`             | <ul><li>Read vulnerability information for Secret scanning</li></ul>                                                                                                                                            |
| **Secrets**                |            `Read & write`            | <ul><li>Optionally write repo secrets after creating new repo</li></ul>                                                                                                                                         |
| **Single file**            | `Read & write` (path to cortex.yaml) | <ul><li>Read cortex.yaml files</li><li>Create cortex.yaml files</li></ul>                                                                                                                                       |
| **Workflows**              |            `Read & write`            | <ul><li>Write in GitHub actions files</li></ul>                                                                                                                                                                 |

#### Organization-level permissions

| Permission                  | Requirement    | Purpose in Cortex                                                                                                                                                     |
| --------------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Administration**          | `Read-only`    | <ul><li>Create repositories</li><li>Pull in Copilot data for <a href="/pages/nZOyOBWYHpwwuH9q8HVF">Eng Intelligence</a></li></ul>                                     |
| **Members**                 | `Read & write` | <ul><li>Read membership information for ownership and team composition</li><li>Write permission used in <a href="/pages/E4BndAJAkJ3sjXz3SAer">Workflows</a></li></ul> |
| **GitHub copilot business** | `Read-only`    | <ul><li>Read copilot related metrics for AI Impact Dashboard</li></ul>                                                                                                |

### Choose a configuration option

There are multiple options for connecting Cortex to your GitHub instance:

* Through Cortex's official GitHub app
  * Note: This is supported for use with a single organization in GitHub.
* Through a custom GitHub app
  * By using Cortex's official GitHub app or a custom GitHub app, users can tag entities with Git details and enable GitOps-style configuration of data in Cortex.
* Using a personal access token
* Using Cortex Axon Relay, a relay broker that allows you to securely connect your on-premises GitHub data.

If your GitHub setup involves multiple organizations, you can add multiple GitHub apps, use a [personal access token](#configuration---personal-access-token) that has access to all orgs, or create multiple configurations with corresponding aliases.

See the tabs below for instructions on each of the GitHub integration options.

{% hint style="info" %}
If you're using a self-hosted instance of GitHub, you'll need to verify that your Cortex instance is able to reach the GitHub instance. We route our requests through a static IP address.

* Reach out to support at <help@cortex.io> to receive details about our static IP. If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your GitHub instance.
  {% endhint %}

{% tabs %}
{% tab title="Cortex GitHub app" %}
**Configure GitHub with the Cortex GitHub app**

[Cortex's official GitHub app](https://github.com/apps/cortex-app) is the easiest way to connect your GitHub instance. It is preconfigured with the [permissions](#prerequisites) needed to use this integration. Note that it is not available for Cortex Server.

To set up the app:

1. In Cortex, navigate to the [GitHub settings page](https://app.getcortexapp.com/admin/integrations/github):
   1. Click **Integrations** from the main nav. Search for and select **GitHub**.
2. On the GitHub settings page, next to `cortex`, click **Install**.\
   ![](/files/2YjpsIRrU7NaEMpCr9kT)
3. Follow the prompts, then click **Install & Authorize**.

Cortex's GitHub app is preconfigured with:

* Permissions for [catalogs](/ingesting-data-into-cortex/catalogs), [Scorecards](/standardize/scorecards), and the [Scaffolder](/streamline/workflows#scaffolder).
* Webhooks to enable [GitOps](/configure/gitops).
* Support for using [GitHub teams](https://docs.github.com/en/organizations/organizing-members-into-teams/about-teams) as an ownership provider.

The app comes with a built-in linter, which validates the format of a given `cortex.yaml` file and checks Cortex-specific items. **However, the linter DOES NOT validate data correctness.** For example, the linter will confirm that the format of a group block is correct, but will not check that the group exists.
{% endtab %}

{% tab title="Custom app" %}
**Configure GitHub with a custom app**

If you're using Cortex Server, or if you don't want to use the official Cortex app, you can connect a custom GitHub app.

Make sure you have configured the permissions listed above under [Prerequisites](#prerequisites).

**Step 1: Register the custom app in GitHub**

1. [Register the app](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app). When you're creating the app, make sure to follow these steps:
   * **Disable** "Expire user authorization tokens." (Cortex does not support this OAuth workflow yet.)
   * **Select** "Request user authorization (OAuth) during installation."
   * **Callback URL:** `https://app.getcortexapp.com/github/redirect/{alias}`
     * Make sure to use the GitHub configuration alias and not the tenant name in the URL.
   * **Webhook URL:** `https://api.getcortexapp.com/api/internal/v1/github/webhook`
   * **Add** a webhook secret of your choosing that will be identical to the webhook secret token configured later in Cortex settings.
   * **Set** the repository and organization [permissions](#api-permissions) outlined in the configuration modal.
   * **Check** `Push` and `Check suite` under **Subscribe to events**.
2. After the app has been created, generate a client secret and private key.

**Step 2: Configure the custom app in Cortex**

1. In Cortex, navigate to the [GitHub settings page](https://app.getcortexapp.com/admin/integrations/github):
   * Click **Integrations** from the main nav. Search for and select **GitHub**.
2. Click **Add configuration**, then for the type, select **GitHub app**.
3. Fill in the form:
   * **Alias:** Enter the name Cortex will associate with a given configuration.
   * **Application ID:** Enter the ID for your custom GitHub ap.
   * **Client ID:** Enter the unique [client ID](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authenticating-to-the-rest-api-with-an-oauth-app#registering-your-app) assigned to your app during registration.
   * **Client secret:** Enter the unique client secret assigned to your app during registration.
   * **Private key:** Enter the [private key](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-github-apps#generating-private-keys) to authenticate with your GitHub app.
   * **Public link:** Enter the public URL of your GitHub app.
   * **API endpoint (for GitHub enterprise):** Enter the endpoint root URL for self-managed GitHub setups.
4. Click **Save**.
5. On the GitHub Settings page in Cortex, under **Webhook**, choose your new configuration alias and enter the same **Secret token** that was entered in GitHub during the app configuration.
6. On the GitHub Settings page in Cortex, next to your custom app configuration's name, click **Install**.
   {% endtab %}

{% tab title="Personal access token" %}
**Configure GitHub with a personal access token**

**Prerequisites**

Before getting started, make sure your [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) has, at minimum, the `repo` and `read:org` permissions.

Note: Beyond the minimum permissions indicated above, many scenarios will require that the user who generated the personal access token have organization ownership permissions within GitHub.

**Configuration**

1. In Cortex, navigate to the [GitHub settings page](https://app.getcortexapp.com/admin/integrations/github):
   * Click **Integrations** from the main nav. Search for and select **GitHub**.
2. Click **Add configuration**.
3. In the upper right corner of the modal, click the dropdown and select **Personal access token**.

   <figure><img src="/files/ZmKO27g2EwJnihbtyTU4" alt=""><figcaption></figcaption></figure>
4. Fill in the form:
   * **Alias:** Enter a name that Cortex will associate with a given configuration.
   * **Token:** Enter the Personal access token generated in GitHub.
   * **API endpoint (for GitHub enterprise):** Enter the endpoint root URL for self-managed GitHub setups.
5. Click **Save**.
   {% endtab %}

{% tab title="Relay broker" %}
**Configure GitHub with Cortex Axon Relay**

See [Internally hosted integrations](/ingesting-data-into-cortex/integrations/axon-relay) for instructions. Make sure to follow the GitHub-specific instructions for the docker-compose.yml file.
{% endtab %}
{% endtabs %}

**Configure the integration for multiple GitHub accounts**[**​**](https://docs.cortex.io/docs/reference/integrations/github#configure-the-integration-for-multiple-propsintegration-accounts)

The GitHub integration has multi-account support. You can add a configuration for each additional organization, instance, or account by repeating the process above.

Each configuration requires an alias, which Cortex uses to correlate the designated organization, instance, or account with registrations for various entities. Registrations can also use a default configuration without a listed alias. You can edit aliases and default configurations from the GitHub page in your Cortex settings. Select the edit icon next to a given configuration and toggle **Set as default** on. If you only have one configuration, it will automatically be set as the default.

Cortex supports mapping multiple identities for a single user if you have multiple configurations of GitHub. See the [Identity mapping documentation](/configure/settings/managing-users/identity-mapping) for more information.

{% hint style="info" %}
To write rules related to Dependabot alerts, you must verify the necessary permissions are set for repositories you'd like to see vulnerabilities reported on.

To verify, navigate to a repository on GitHub and click "Settings" → "Code security and analysis". Make sure you are a member of a team under "Access to alerts.
{% endhint %}

## Registration

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on importing entities.

### Entity descriptor

**Repository**

You can define a GitHub repository for a given entity by adding the `x-cortex-git` block to the entity's descriptor. When you define a repository, Cortex checks for Security Advisory vulnerabilities from the GraphQL API and Advanced Security vulnerabilities from the Rest API.

```yaml
x-cortex-git:
  github:
    repository: cortex/docs
    basepath: myService
    alias: myApp
```

| Field        | Description                                                                                                                                                                              | Required |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------: |
| `repository` | GitHub repository in the form `/`                                                                                                                                                        |   **✓**  |
| `basepath`   | Subdirectory for the entity if it is in a monorepo. Note that setting a `basepath` filters the vulnerabilities that appear in Cortex; Advanced Security vulnerabilities will not appear. |          |
| `alias`      | Alias for the configuration in Cortex (only needed if you have opted into multi-account support)                                                                                         |          |

Only one repository can be defined for in a given entity's YAML in the `x-cortex-git` block. Users looking to list additional repositories without the full functionality of GitOps can define the repos as custom data.

```yaml
x-cortex-custom-metadata:
  second-git-repo:
    - `/`
  third-git-repo:
    - `/`
```

**Ownership**

You can define the following block in your Cortex entity descriptor to add your GitHub teams. Be sure to include both your GitHub organization name and the team name in the `name` field.

```yaml
x-cortex-owners:
  - type: group
    name: cortex/engineering
    provider: GITHUB
    description: This is a description for this GitHub team that owns this entity.
```

| Field         | Description                                                                                                                                                                                                 | Required |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------: |
| `type`        | Ownership type; must be defined as `group` for GitHub teams                                                                                                                                                 |   **✓**  |
| `name`        | GitHub team name in the form `/`Team names are generally converted to lowercase with `-` separators (`Team Name` would be `cortex/team-name`), but you can verify your exact name from the GitHub permalink |   **✓**  |
| `provider`    | Name of integration (in this case, `GITHUB`)                                                                                                                                                                |   **✓**  |
| `description` | Description for the GitHub team                                                                                                                                                                             |          |

{% hint style="warning" %}
Multiple GitHub organizations are not supported for ownership, and Cortex will use the default configuration when fetching teams.
{% endhint %}

### Identity mappings

Cortex maps users' email addresses to discovered GitHub accounts, so you never need to define email ownership in an entity descriptor. Users must be members of GitHub teams to be pulled in to Cortex.

You can confirm users' GitHub accounts are connected from [GitHub identity mappings in settings](https://app.getcortexapp.com/admin/settings/github-mappings).

## Using the GitHub integration

### View GitHub data on entity pages in Cortex

The GitHub integration will populate the **Repo** and **Language** detail blocks on an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details). If a GitHub team has been [defined as the owner](#ownership) for an entity, it will also appear in the **Owners** block.

#### Code & security

Vulnerabilities appear in the **Vulnerabilities** block under **Code & security** on an entity page overview.

Click **Code & security** in an entity's sidebar to view the full list of vulnerabilities for an entity. Cortex checks for:

* Security Advisory vulnerabilities from the GraphQL API
* [GitHub Advanced Security](https://docs.github.com/en/get-started/learning-about-github/about-github-advanced-security) vulnerabilities
  * Cortex pulls data from code scanning, Dependabot alerts, CodeQL, and Secret scanning.
  * Dependency reviews are not supported.

GitHub Advanced Security vulnerabilities are not surfaced for monorepos.

{% hint style="success" %}
You can query for vulnerabilities with CQL and create Scorecard rules based on security metrics. See [Scorecards and CQL](#scorecards-and-cql) below.
{% endhint %}

#### **Events**

Recent commits appear at the top of an entity's overview page.

You can also click **Events** in the entity's sidebar to see all commits and releases associated with that entity. Each is hyperlinked to the commit or release page in GitHub and includes a timestamp.

#### **Repository**

You can access more detailed information pulled from GitHub in the **Repository** page in the sidebar. At the top of the page, you'll find the repo(s) associated with that entity and the most-used language in files for that entity. In the **Top contributors** block, you'll find the three users who have contributed the most code and the number of their contributions.

In the **Commits** section, you'll find the 10 most recent commits and metadata about each. Below **Commits** is the **Recent releases** section, which includes the 5 most recent releases.

#### **Issue tracking**

From the **Issue tracking** page in the entity's sidebar, you can find a list of open [GitHub issues](https://docs.github.com/en/issues). Each issue will show the number, title, assignees, and date created.

#### **Packages**

Packages are automatically scraped from your Git repos or they can be submitted via the [packages API](/api/readme/packages). The package file must be in the root of your repository — or, if you're using `basepath`, in the root of the subdirectory — to be scraped by Cortex. You can query an entity's packages in [CQL explorer](https://app.getcortexapp.com/admin/cql-explorer) using `packages()`.

To view packages, click **Packages** in the entity's sidebar.

The following package types are automatically scraped from repositories:

* JavaScript / Node.js: `package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`
* Python: `requirements.txt`, `pipfile.lock`
* .NET (C#): `packages.lock.json`
* Java: `pom.xml`
* Go: `go.sum`

All other files of these types can be added via the [packages API](/api/readme/packages).

#### **CI/CD - GitHub workflows**

From the **CI/CD > GitHub workflows** page in the entity's sidebar, you can find a history of [GitHub workflow](https://docs.github.com/en/actions/using-workflows/about-workflows) runs for the past week. Each run is tagged with its status: `IN_PROGRESS`, `COMPLETED`, `SUCCESS`, `CANCELLED`, `FAILURE`, `PAUSED`.

The **GitHub workflows** page displays data about workflows in GitHub, **not** Workflows initiated via [Cortex's Workflows tool](/streamline/workflows).

### Team entity pages

When a [GitHub team is registered](#ownership) with a team entity, Cortex will pull GitHub users in to the **Members** tab. When available, Cortex will pull in the profile picture and email address for each user.

### Engineering homepage

The GitHub integration enables Cortex to pull information about pull requests and issues into the [homepage](/streamline/homepage). You can find your open pull requests, any pull requests assigned to you for review, and any issues assigned to you.

Pull requests and issues from GitHub are refreshed every 2 minutes.

### Eng Intelligence

The [Eng Intelligence tool](/improve/eng-intelligence) uses pull request data from GitHub to generate metrics:

* Average PR open to close time
* Avg time to first review
* Avg time to approval
* PRs opened
* Weekly PRs merged
* Avg PRs reviewed/week
* Avg commits per PR
* Ave lines of code changed per PR

Eng Intelligence also pulls in data from Copilot to show AI impact in the [Copilot Dashboard](/improve/eng-intelligence/dashboards/ai-impact).

You can read more about how Eng Intelligence tracks metrics for teams and users in the [Eng Intelligence documentation](/improve/eng-intelligence).

To add deployments for your Github related entity, you can send a deployment event to the [Cortex API.](/api/readme/deploys)

### Scorecards and CQL

With the GitHub integration, you can create Scorecard rules and write CQL queries based on GitHub data.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Approvals required to merge</summary>

Number of approvals required to merge a pull/merge request into a repository. Defaults to 0 if no approvals are defined.

**Definition**: `git.numOfRequiredApprovals()`

**Examples**

For a security or development maturity Scorecard, you can write a rule to make sure at least one approval is required to merge a pull/merge request:

```
git.numOfRequiredApprovals() > 0
```

By having a rigorous PR process in place for a repo, you can make sure changes aren't made that create vulnerabilities. This kind of rule could also be used in a best practices or project standards Scorecard.

You can also use a similar expression in the Query Builder to find entities lacking approval:

```
git.numOfRequiredApprovals() < 1
```

</details>

<details>

<summary>Git repository set</summary>

Check if an entity has a registered Git repository.

**Definition:** `git (==/!=) null: Boolean`

**Example**

In a Scorecard, you can write a rule that detects whether an entity has a Git repository set:

```
git != null
```

</details>

<details>

<summary>Branches</summary>

List all live branches with some basic metadata.

* Head
* Is protected
* Name

**Definition**: `git.branches()`

**Example**

For a best practices Scorecard, you can make sure that branches associated with an entity match a standard naming convention:

```
git.branches().all((branch) => branch.name.matches("(main|master|feat-.*|bug-.*|task-.*)"))
```

</details>

<details>

<summary>Branch protection details</summary>

Find details for specified branch, or default branch if none is specified.

* Branch name
* Code owner reviews required
* Dismiss stale reviews
* Required status checks
* Restrictions apply to admin
* Review required

**Definition:** `git.branchProtection()`

**Examples**

For a security Scorecard, you can write a rule to make sure the default branch is protected:

```
git.branchProtection() != null
```

Because vulnerabilities in the default branch are critical, this rule should be in one of the first couple levels.

You can also use the Query Builder to find entities with unprotected default branches:

```
git.branchProtection() = null
```

</details>

<details>

<summary>Commits</summary>

Get the latest commits **(to a maximum of 100)** for a defined lookback period **(defaulting to 7 days)**.

* Date
* Message
* SHA
* URL
* Username

These results can be filtered based on branch name, using the default branch if no other branch is provided.

**Definition:** `git.commits()`

**Example**

You can use the `git.commits()` expression in a security Scorecard to make sure entities have fewer than three commits to a "security-fixes" branch in the last week:

```
git.commits(branchName="security-fixes").length < 3
```

Entities passing this rule will include those that haven't needed three or more security fixes. This can indicate that there aren't vulnerabilities in a given entity's code, but could also suggest that fixes aren't being implemented. Using this rule in conjunction with one focused on vulnerabilities could provide the extra context needed to gain a better understanding of what's happening.

</details>

<details>

<summary>Default branch</summary>

Default branch for the repository, or `main` when null.

**Definition:** `git.defaultBranch()`

**Example**

If default branches should always be named "main," you can write a rule to make sure entities follow this practice:

```
git.defaultBranch().matches("main")
```

</details>

<details>

<summary>File contents</summary>

Load the contents of a file from the entity's associated repository.

The contents can be validated by using string comparison operations or parsed by the built-in jq function. The jq function will automatically coerce file contents of JSON or YAML formats.

**Definition:** `git.fileContents()`

**Example**

For a Scorecard focused on development maturity, you could use the `git.fileContents()` rule to enforce that a CI pipeline exists, and that there is a testing step defined in the pipeline.

```
git.fileContents("circleci/config.yml").matches(".*npm test.*")
```

A best practices Scorecard, meanwhile, could use this expression for a number of rules:

* To make sure node engine version in specified in the `package.json` file:

  ```
  jq(git.fileContents("package.json"), ".engines.node") != null
  ```
* To make sure TypeScript projects have a `tsconfig.json` file checked in:

  ```
  jq(git.fileContents("package.json"), ".devDependencies | with_entries(select(.key == \"typescript\")) | length") == 0 or git.fileExists("tsconfig.json")
  ```
* To make sure projects using yarn do not allow NPM:

  ```
  jq(git.fileContents("package.json"), ".engines.yarn") == null or jq(git.fileContents("package.json"), ".engine.npm") = "please-use-yarn"
  ```
* And to ensure the yarn version being used is not deprecated:

  ```
  jq(git.fileContents("package.json"), ".engines.yarn") == null or !(semver("1.2.0") ~= semverRange(jq(git.fileContents("package.json"), ".engines.yarn")))
  ```

</details>

<details>

<summary>File exists</summary>

Check if file exists from within the entity's associated repository.

**Definition:** `git.fileExists()`

**Examples**

For a Scorecard focused on best practices, you can make sure that repositories contain a README.md file:

```
git.fileExists("README.md")
```

This rule would make sense in the first level because it's so essential.

A higher-level rule in a best practices Scorecard might confirm that developers are checking in lockfiles to ensure consistency in package installs:

```
git.fileExists("yarn.lock") OR git.fileExists("package-lock.json")
```

And/or a rule that makes sure there are unit tests enabled:

```
git.fileExists("*Test.java")
```

Finally, you could write a rule to make sure projects have a standard linter:

```
git.fileExists(".prettierrc.json") OR git.fileExists(".eslintrc.js")
```

</details>

<details>

<summary>Number of Git vulnerabilities</summary>

Check the number of vulnerabilities for an entity's associated repository.

You can filter by severity (by default searches by all severities) or source (by default only searches GitHub security advisories).

**When using the GitHub Advanced Security source, severities displayed in the UI may not match severities returned by the API.**

**Definition:** `git.numOfVulnerabilities()`

**Examples**

A security-focused Scorecard will likely include a rule making sure there are no Git vulnerabilities:

```
git.numOfVulnerabilities() == 0
```

You can use Scorecard levels to stratify vulnerabilities by risk. An initial level might make sure there are no critical vulnerabilities:

```
git.numOfVulnerabilities(severity=["CRITICAL"]) == 0
```

While a higher level might make sure there are no vulnerability warnings:

```
git.numOfVulnerabilities(severity=["WARNING"]) == 0
```

</details>

<details>

<summary>List of Git vulnerabilities</summary>

Lists the vulnerabilities for an entity's associated repository. You can filter by severity (by default searches by all severities) or source (by default only searches GitHub security advisories). Note when using the GitHub Advanced Security source, severities displayed in the UI may not match severities returned by the API.

**Definition**: `git.vulnerabilities()`

**Examples**

You could write a Scorecard rule that verifies an entity has fewer than 5 Git vulnerabilities:

```
git.vulnerabilities().length < 5
```

You could write a rule that verifies the entity has no vulnerabilities with "High" or "Critical" severity sourced from GitHub Advanced Security:

```
git.vulnerabilities(severity=["CRITICAL", "HIGH"], source=["GITHUB_ADVANCED_SECURITY"]).length < 1
```

</details>

<details>

<summary>Has Cortex YAML</summary>

Check if a repository has a valid `cortex.yaml` file checked in at the root directory (when GitOps is enabled).

**Definition:** `git.hasCortexYaml()`

**Example**

If you're using a Scorecard to track a migration from Cortex UI to GitOps, you can use this rule to make sure entities are set up for GitOps management of entity descriptors:

```
git.hasCortexYaml() == true
```

</details>

<details>

<summary>Last commit details</summary>

Provides last commit details.

* Date
* Message
* SHA
* URL
* Username

**Definition:** `git.lastCommit()`

**Examples**

One of the first rules you might write for a Scorecard focused on development maturity or security is one validating that the last commit was within the last month:

```
git.lastCommit().freshness < duration("P1M")
```

As counterintuitive as it may seem, services that are committed too infrequently are actually at more risk. People who are familiar with the service may leave a team, institutional knowledge accumulates, and from a technical standpoint, the service may be running outdated versions of your platform tooling.

Depending on best practices at your organization, you may want to confirm entities are updated within a week:

```
git.lastCommit().freshness < duration("P7D")
```

Confirming whether a service was updated within the last week can help team members catch outdated code sooner. Plus, if there is a security issue, you can quickly determine which services have or have not been updated to patch the vulnerability.

</details>

<details>

<summary>Pull requests</summary>

Lists pull requests opened during a defined lookback period.

* Approval date
* Author
* Date closed
* Date opened
* First review date
* Last updated
* Number of commits
* Number of lines added
* Number of lines deleted
* Organization
* Repository
* Source
* Status
* URL

**Definition:** `git.pullRequests()`

**Example**

You can use the `git.pullRequests()` query to find entities that have a small number of pull requests opened in the last two weeks:

```
git.pullRequests(lookback=duration("P14D")).length < 3
```

This can highlight entities that haven't been updated recently, which may be especially useful when entities have to be updated to address a vulnerability.

</details>

<details>

<summary>Reviews</summary>

List reviews left during a defined lookback period.

* Organization
* Repository
* Review date
* Reviewer

**Definition:** `git.reviews()`

**Examples**

A development maturity Scorecard might use the `git.reviews()` expression to make sure that there is a rigorous review process in place before changes are implemented:

```
git.reviews(lookback=duration("P7D")).length > 25
```

This rule makes sure that there are more than 25 reviews left in the last week.

</details>

<details>

<summary>Workflow runs</summary>

Get workflow runs meeting given filter criteria, including conclusions, statuses, and a lookback period.

* Conclusion
* Name
* Run started at
* Run time
* Run updated at
* Status

Conclusions: `FAILURE`, `SUCCESS`, `TIMED_OUT`

Statuses: `QUEUED`, `IN_PROGRESS`, `COMPLETED`

The lookback period specifies a duration for which returned runs should be created within, defaulting to a period of 3 days.

* The `runTime` of the `WorkflowRun` object represents the difference between `runStartedAt` and `runUpdatedAt` times in seconds.

**Definition:** `git.workflowRuns()`

**Example**

To make sure an entity has had a successful workflow run within the last two weeks, you can write a rule like:

```
git.workflowRuns(conclusions=["SUCCESS"], statuses=["COMPLETED"], lookback=duration("P14D")).length > 0
```

This rule is checking for GitHub workflow runs with a `SUCCESS` conclusion and `COMPLETED` status during a 14-day lookback window.\\

To find the percentage of successes in workflow runs, you could write a query similar to:

```
(git.workflowRuns(conclusions=["SUCCESS"], lookback=duration("P1D")).length) / (git.workflowRuns(lookback=duration("P1D")).length) * 100
```

</details>

**Ownership CQL**

<details>

<summary>All ownership details</summary>

A special built-in type that supports a null check or a count check, used to enforce ownership of entities.

**Definition:** `ownership: Ownership | Null`

**Example**

An initial level in a security Scorecard might include a rule to ensure an entity has at least one team as an owner:

```
ownership.teams().length > 0
```

</details>

<details>

<summary>All owner details</summary>

List of owners, including team members and individual users, for each entity

**Definition:** `ownership.allOwners()`

**Example**

The Scorecard might include a rule to ensure that entity owners all have an email set:

```
ownership.allOwners().all((member) => member.email != null)
```

</details>

<details>

<summary>Team details</summary>

List of teams for each entity

**Definition:** `ownership.teams(): List<Team>`

**Example**

The Scorecard might include a rule to ensure that an entity owners all have a description and are not archived:

```
ownership.teams().all(team => team.description != null and team.isArchived == false)
```

</details>

**Copilot CQL**

<details>

<summary>AI adoption</summary>

The ratio of licensed seats that were active users of AI coding tools in a given time period. Returns a value between 0 and 1, where 1 represents 100% adoption. Note: This metric is only available for Team entities.

**Definition**: `aiTools.analysis(lookback: Duration).aiAdoptionRate`

**Example**

You could create a Scorecard rule to make sure AI adoption rate is at least 50% over the previous 30 days:

```
aiTools.analysis(lookback = duration("P30D")).aiAdoptionRate >= 0.5
```

</details>

<details>

<summary>Active AI users</summary>

The number of users who used AI coding tools in a given time period. Note: This metric is only available for Team entities.

**Definition**: `aiTools.analysis(lookback: Duration).activeAiUsers`

**Example**

You could create a Scorecard rule to verify you had at least 5 active AI users in the last 7 days:

```
aiTools.analysis(lookback = duration("P7D")).activeAiUsers >= 5
```

</details>

**External repositories**

By default, each GitHub rule is evaluated on the repository defined in a given entity descriptor. If the base path parameter has been set, CQL rules will automatically scope to the base path subdirectory.

To evaluate the rule for a service for an external repository, pass the repo identifier in the `git(repoIdentifier: Text)` command (e.g. `git("github:org/repositoryName")`).

This can be combined with other CQL rules. For example, a rule based on a dynamic external repository with custom data would be `git("github:" + custom("my-custom-repo")).fileExists("README.md")`.

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex conducts a background sync of GitHub identities every day at 10 a.m. UTC. Pull requests and issues are refreshed about every 10 minutes.

## FAQs and troubleshooting

**I'm getting this error: `"{"message":"Not Found", "documentation_url":"https://docs.github.com/rest/repos#get-a-repository"}"`.**

If you've set up multiple GitHub accounts/organizations, Cortex will not be able to identify the correct one unless the `alias` variable is defined.

**What if I have multiple email addresses set in my GitHub account?**

Cortex will only detect the primary email address associated with your GitHub account **if it is public**.

If Cortex is not correctly pulling in user emails, ensure the given user(s) have allowed their email address to be public. Make sure the **"Keep my email address private"** setting is **unchecked** in the user's personal GitHub settings.

**My ownership isn't being automatically mapped through GitHub.**

If the email address associated with your Cortex account is not the same as your GitHub email address, you need to add your Cortex email address to the **Public email** dropdown in GitHub settings.

Github OAuth, which you can configure in Cortex user settings, allows you to link your GitHub username with your Cortex account, even if you don't have a public email set up on GitHub.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# GitLab

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[GitLab](https://about.gitlab.com/) is a Git-based version control system with cloud and self-hosted options.

Integrating GitLab with Cortex allows you to:

* Discover and track ownership of entities
* Follow a [GitOps](/configure/gitops) workflow with GitLab
* View commits alongside events and other data on [entity pages in Cortex](#view-gitlab-data-on-entity-pages-in-cortex)
* View information about merge requests in the [engineering homepage](#engineering-homepage)
* Use GitLab metrics in [Eng Intelligence](#eng-intelligence) to understand key metrics and gain insight into services, incident response, and more
* Create [Scorecards](#scorecards-and-cql) to monitor development maturity relating to GitLab projects

## How to configure GitLab with Cortex

There are two options for integrating GitLab: the default configuration method and Cortex Axon Relay, a relay broker allows you to securely connect your on-premises GitLab data.

### Prerequisites

Before getting started:

* A GitLab user with at least the `Maintainer` role must create a GitLab [personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) or [group access token](https://docs.gitlab.com/ee/user/group/settings/group_access_tokens.html) with the `read_api` scope.
  * We recommend that you create the token at the parent group level, as GitLab does not support using a scoped token to read members from a parent group. If you do not create the token at the parent level, then you will need to manually configure groups in your GitLab settings in order for identity mapping and teams to work as expected.
  * Note that `Maintainer` is sufficient for project/repo data, but retrieving user emails for identity mapping typically requires an `Owner`- or `Admin`-generated token with `api` or `read_user` scope, particularly in enterprise/SSO environments.
* If you're using the Scaffolder for entities in a given GitLab instance, make sure that configuration has the full `api` scope.

#### Self-hosted prerequisites

If you're using a self-hosted instance of GitLab, you'll need to verify that your Cortex instance is able to reach the GitLab instance.\
\
We route our requests through a static IP address. Reach out to support at <help@cortex.io> to receive details about our static IP. If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your GitLab instance.

{% tabs %}
{% tab title="Standard configuration" %}
**Configure the integration in Cortex**

1. In Cortex, navigate to the [GitLab settings page](https://app.getcortexapp.com/admin/integrations/gitlab):
   * Click **Integrations** from the main nav. Search for and select **GitLab**.
2. Click **Add configuration**.
3. Configure the GitLab integration form:
   * **Account alias**: Enter the alias you will use to tie entity registrations to different configuration accounts.
   * **Token**: Enter your personal or group access token.
   * **Host**: Enter your host. If using a custom GitLab instance, enter the URL without the API path (e.g. `https://gitlab.getcortexapp.com`)
   * **Hide personal projects**: Toggle this setting on if you do not want your personal projects pulled in to Cortex. Toggle this setting off to allow Cortex to pull your personal projects.
4. Click **Save**.
   {% endtab %}

{% tab title="Relay broker" %}
**Configure GitLab with Cortex Axon Relay**

See [Internally hosted integrations](/ingesting-data-into-cortex/integrations/axon-relay) for instructions. Make sure to follow the GitLab-specific instructions for the docker-compose.yml file.
{% endtab %}
{% endtabs %}

Once you save your configuration, you'll see it listed on the integration's settings page in Cortex. If you’ve set everything up correctly, you’ll see the option to **Remove Integration** in Settings.

You can also use the **Test all configurations** button to confirm that the configuration was successful. If your configuration is valid, you’ll see a banner that says “Configuration is valid. If you see issues, please see documentation or reach out to Cortex support.”

**Configure the integration for multiple GitLab accounts**[**​**](https://docs.cortex.io/docs/reference/integrations/gitlab#configure-the-integration-for-multiple-propsintegration-accounts)

The GitLab integration has multi-account support. You can add a configuration for each additional by repeating the process above.

Each configuration requires an alias, which Cortex uses to correlate the designated with registrations for various entities. Registrations can also use a default configuration without a listed alias. You can edit aliases and default configurations from the GitLab page in your Cortex settings. Select the edit icon next to a given configuration and toggle **Set as default** on. If you only have one configuration, it will automatically be set as the default.

Cortex supports mapping multiple identities for a single user if you have multiple configurations of GitLab. See the [Identity mapping documentation](/configure/settings/managing-users/identity-mapping) for more information.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## Enable GitOps for your GitLab integration

Cortex supports a GitOps approach, which allows you to manage entities in Cortex through your version control system. If you would prefer this workflow over the UI for the GitLab integration, you must create a webhook. Please see the [Cortex GitOps documentation](/configure/gitops) for instructions.

## How to connect Cortex entities to GitLab

### Import entities

Cortex will discover entities for import from your GitLab configuration(s). These will appear in the import entities workflow.

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on importing entities manually.

### Editing the entity descriptor

**Git**

By specifying the `x-cortex-git` field in your Cortex entity descriptor, you'll be able to see Git information in the entity page, including the top language, recent commits, and top contributors.

```yaml
x-cortex-git:
  gitlab:
    repository: cortex/docs
    basepath: myService
    alias: myApp
```

| Field        | Description                                                                                      | Required |
| ------------ | ------------------------------------------------------------------------------------------------ | :------: |
| `repository` | GitLab project ID or `namespace/repo` as defined in GitLab                                       |   **✓**  |
| `basepath`   | Subdirectory for the entity if it is in a monorepo                                               |          |
| `alias`      | Alias for the configuration in Cortex (only needed if you have opted into multi-account support) |          |

Only one repository can be defined for in a given entity's YAML in the `x-cortex-git` block.

**Ownership**

You can define the following block in your Cortex entity descriptor to add your GitLab groups.

Team name should match the group name in GitLab.

```yaml
x-cortex-owners:
  - type: group
    name: Team Name
    provider: GITLAB
    description: This is a description for this owner
```

| Field         | Description                                                 | Required |
| ------------- | ----------------------------------------------------------- | :------: |
| `type`        | Ownership type; must be defined as `group` for GitLab teams |   **✓**  |
| `name`        | GitLab team name                                            |   **✓**  |
| `provider`    | Name of integration (in this case, `GITLAB`)                |   **✓**  |
| `description` | Description for the GitLab team                             |          |

### Identity mapping

Cortex maps users' email addresses to discovered GitLab accounts, so you never need to define email ownership in an entity descriptor.

You can confirm users' GitLab accounts are connected from [GitLab identity mappings in settings](https://app.getcortexapp.com/admin/settings/gitlab-mappings).

If users are not loading in the identity mapping page, make sure that you have created your GitLab personal access token from the parent level as described in the [Prerequisites](#prerequisites).

## Using the GitLab integration

### View GitLab data on entity pages in Cortex

Cortex uses the GitLab integration for a significant amount of data that appears on [entities' detail pages](/ingesting-data-into-cortex/entities-overview/entities/details).

The GitLab integration will populate the **Repo** and **Language** detail blocks on an entity's details page.

In the **Recent activity preview**, you'll find the recent commits and releases. These will also appear in the event timeline.

These data will appear for entities imported from a Git source or those that have a Git repo defined in their YAMLs.

#### **Events**

On an entity's **Events** page, you can find all of the commits and releases associated with that entity. Each is hyperlinked to the commit or release page in GitLab and includes a timestamp.

#### **CI/CD**

To see pipeline runs for GitLab, use the [deploys API](/ingesting-data-into-cortex/entities-overview/entities/deploys) to add deploy information. After doing this, from the **CI/CD > Deploys** page in the entity's sidebar, you will see a history of pipeline runs.

#### **Repository**

You can access more detailed information pulled from GitLab in the **Repository** page in the entity's sidebar. At the top of the page, you'll find the repo associated with that entity and the most-used language in files for that entity. In the **Top contributors** block, you'll find the three users who have contributed the most code and the number of their contributions.

In the Commits section, you'll find the 10 most recent commits and metadata about each. Below Commits is the Recent releases section, which includes the 5 most recent releases.

#### **Packages**

Packages are automatically scraped from your Git repos or they can be submitted via the [packages API](/api/readme/packages). The package file must be in the root of your repository — or, if you're using `basepath`, in the root of the subdirectory — to be scraped by Cortex. You can query an entity's packages in [CQL explorer](https://app.getcortexapp.com/admin/cql-explorer) using `packages()`.

To view packages, click **Packages** in the entity's sidebar.

The following package types are automatically scraped from repositories:

* JavaScript / Node.js: `package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`
* Python: `requirements.txt`, `pipfile.lock`
* .NET (C#): `packages.lock.json`
* Java: `pom.xml`
* Go: `go.sum`

All other files of these types can be added via the [packages API](/api/readme/packages).

#### Team pages

When a GitLab team is registered in a team entity descriptor, Cortex will pull GitLab users in to the **Members** tab. When available, Cortex will pull in the profile picture and email address for each user.

If team members are not appearing as expected, make sure that you have created your GitLab personal access token from the parent level as described in the [Prerequisites](#prerequisites).

### Engineering homepage

The GitLab integration enables Cortex to pull information about merge requests into the [homepage](/streamline/homepage). You can find your open merge requests and any merge requests assigned to you for review.

Merge requests from GitLab are refreshed every 2 minutes.

### Eng Intelligence

The [Eng Intelligence tool](/improve/eng-intelligence) also uses merge request data from GitLab to generate metrics:

* Average MR open to close time
* Avg time to first review
* Avg time to approval
* MRs opened
* Weekly MRs merged
* Avg MRs reviewed/week
* Avg commits per MR
* Avg lines of code changed per MR

You can read more about how Eng Intelligence tracks metrics for teams and users in the Eng Intelligence walkthrough.

To add deployments for your GitLab related entity, you can send a deployment event to the [Cortex API](/api/readme/deploys).

### Scorecards and CQL

With the GitLab integration, you can create Scorecard rules and write CQL queries based on GitLab data.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Approvals required to merge</summary>

Number of approvals required to merge a pull/merge request into a repository. Defaults to 0 if no approvals are defined.

**Definition**: `git.numOfRequiredApprovals()`

**Examples**

For a security or development maturity Scorecard, you can write a rule to make sure at least one approval is required to merge a pull/merge request:

```
git.numOfRequiredApprovals() > 0
```

By having a rigorous PR process in place for a repo, you can make sure changes aren't made that create vulnerabilities. This kind of rule could also be used in a best practices or project standards Scorecard.

You can also use a similar expression in the Query Builder to find entities lacking approval:

```
git.numOfRequiredApprovals() < 1
```

</details>

<details>

<summary>Git repository set</summary>

Check if an entity has a registered Git repository.

**Definition:** `git (==/!=) null: Boolean`

**Example**

In a Scorecard, you can write a rule that detects whether an entity has a Git repository set:

```
git != null
```

</details>

<details>

<summary>Pipeline build success rate</summary>

The percentage of build pipelines that complete successfully. This is calculated against builds on the default branch, for commits in the last 30 days. The calculation is # successful builds / (# successful + # failed).

**Definition:** `git.percentBuildSuccess(): Number`

**Example**

In a Scorecard, you can write a rule that requires at least 90% of build runs to be successful:

```
git.percentBuildSuccess() > 0.9
```

</details>

<details>

<summary>Branches</summary>

List all live branches with some basic metadata.

* Head
* Is protected
* Name

**Definition**: `git.branches()`

**Example**

For a best practices Scorecard, you can make sure that branches associated with an entity match a standard naming convention:

```
git.branches().all((branch) => branch.name.matches("(main|master|feat-.*|bug-.*|task-.*)"))
```

</details>

<details>

<summary>Branch protection details</summary>

Find details for specified branch, or default branch if none is specified.

* Branch name
* Code owner reviews required
* Dismiss stale reviews
* Required status checks
* Restrictions apply to admin
* Review required

**Definition:** `git.branchProtection()`

**Examples**

For a security Scorecard, you can write a rule to make sure the default branch is protected:

```
git.branchProtection() != null
```

Because vulnerabilities in the default branch are critical, this rule should be in one of the first couple levels.

You can also use the Query Builder to find entities with unprotected default branches:

```
git.branchProtection() = null
```

</details>

<details>

<summary>Commits</summary>

Get the latest commits **(to a maximum of 100)** for a defined lookback period **(defaulting to 7 days)**.

* Date
* Message
* SHA
* URL
* Username

These results can be filtered based on branch name, using the default branch if no other branch is provided.

**Definition:** `git.commits()`

**Example**

You can use the `git.commits()` expression in a security Scorecard to make sure entities have fewer than three commits to a "security-fixes" branch in the last week:

```
git.commits(branch="security-fixes", lookback=duration("P7D")).length < 3
```

Entities passing this rule will include those that haven't needed three or more security fixes. This can indicate that there aren't vulnerabilities in a given entity's code, but could also suggest that fixes aren't being implemented. Using this rule in conjunction with one focused on vulnerabilities could provide the extra context needed to gain a better understanding of what's happening.

</details>

<details>

<summary>Default branch</summary>

Default branch for the repository, or `main` when null.

**Definition:** `git.defaultBranch()`

**Example**

If default branches should always be named "main," you can write a rule to make sure entities follow this practice:

```
git.defaultBranch().matches("main")
```

</details>

<details>

<summary>File contents</summary>

Load the contents of a file from the entity's associated repository.

The contents can be validated by using string comparison operations or parsed by the built-in jq function. The jq function will automatically coerce file contents of JSON or YAML formats.

**Definition:** `git.fileContents()`

**Example**

For a Scorecard focused on development maturity, you could use the `git.fileContents()` rule to enforce that a CI pipeline exists, and that there is a testing step defined in the pipeline.

```
git.fileContents("circleci/config.yml").matches(".*npm test.*")
```

A best practices Scorecard, meanwhile, could use this expression for a number of rules:

* To make sure node engine version in specified in the `package.json` file:

  ```
  jq(git.fileContents("package.json"), ".engines.node") != null
  ```
* To make sure TypeScript projects have a `tsconfig.json` file checked in:

  ```
  jq(git.fileContents("package.json"), ".devDependencies | with_entries(select(.key == \"typescript\")) | length") == 0 or git.fileExists("tsconfig.json")
  ```
* To make sure projects using yarn do not allow NPM:

  ```
  jq(git.fileContents("package.json"), ".engines.yarn") == null or jq(git.fileContents("package.json"), ".engine.npm") = "please-use-yarn"
  ```
* And to ensure the yarn version being used is not deprecated:

  ```
  jq(git.fileContents("package.json"), ".engines.yarn") == null or !(semver("1.2.0") ~= semverRange(jq(git.fileContents("package.json"), ".engines.yarn")))
  ```

</details>

<details>

<summary>File exists</summary>

Check if file exists from within the entity's associated repository.

**Definition:** `git.fileExists()`

**Examples**

For a Scorecard focused on best practices, you can make sure that repositories contain a README.md file:

```
git.fileExists("README.md")
```

This rule would make sense in the first level because it's so essential.

A higher-level rule in a best practices Scorecard might confirm that developers are checking in lockfiles to ensure consistency in package installs:

```
git.fileExists("yarn.lock") OR git.fileExists("package-lock.json")
```

And/or a rule that makes sure there are unit tests enabled:

```
git.fileExists("*Test.java")
```

Finally, you could write a rule to make sure projects have a standard linter:

```
git.fileExists(".prettierrc.json") OR git.fileExists(".eslintrc.js")
```

</details>

<details>

<summary>Number of Git vulnerabilities</summary>

Check the number of vulnerabilities for an entity's associated repository.

**Definition:** `git.numOfVulnerabilities()`

**Examples**

A security-focused Scorecard will likely include a rule making sure there are no Git vulnerabilities:

```
git.numOfVulnerabilities() == 0
```

You can use Scorecard levels to stratify vulnerabilities by risk. An initial level might make sure there are no critical vulnerabilities:

```
git.numOfVulnerabilities(severity=["CRITICAL"]) == 0
```

While a higher level might make sure there are no vulnerability warnings:

```
git.numOfVulnerabilities(severity=["WARNING"]) == 0
```

</details>

<details>

<summary>List of Git vulnerabilities</summary>

Find all vulnerabilities within a repository. Can filter by severity or scan type.

**Definition**: `git.vulnerabilities()`

**Examples**

You could write a Scorecard rule that verifies an entity has fewer than 5 Git vulnerabilities:

```
git.vulnerabilities().length < 5
```

You could write a rule to verify that an entity has no critical vulnerabilities:

```
git.vulnerabilities(severity=["CRITICAL"]).length == 0
```

</details>

<details>

<summary>Has Cortex YAML</summary>

Check if a repository has a valid `cortex.yaml` file checked in at the root directory (when GitOps is enabled).

**Definition:** `git.hasCortexYaml()`

**Example**

If you're using a Scorecard to track a migration from Cortex UI to GitOps, you can use this rule to make sure entities are set up for GitOps management of entity descriptors:

```
git.hasCortexYaml() == true
```

</details>

<details>

<summary>Last commit details</summary>

Provides last commit details.

* Date
* Message
* SHA
* URL
* Username

**Definition:** `git.lastCommit()`

**Examples**

One of the first rules you might write for a Scorecard focused on development maturity or security is one validating that the last commit was within the last month:

```
git.lastCommit().freshness < duration("P1M")
```

As counterintuitive as it may seem, services that are committed too infrequently are actually at more risk. People who are familiar with the service may leave a team, institutional knowledge accumulates, and from a technical standpoint, the service may be running outdated versions of your platform tooling.

Depending on best practices at your organization, you may want to confirm entities are updated within a week:

```
git.lastCommit().freshness < duration("P7D")
```

Confirming whether a service was updated within the last week can help team members catch outdated code sooner. Plus, if there is a security issue, you can quickly determine which services have or have not been updated to patch the vulnerability.

</details>

<details>

<summary>Pull requests</summary>

Lists pull requests opened during a defined lookback period.

* Approval date
* Author
* Date closed
* Date opened
* First review date
* Last updated
* Number of commits
* Number of lines added
* Number of lines deleted
* Organization
* Repository
* Source
* Status
* URL

**Definition:** `git.pullRequests()`

**Example**

You can use the `git.pullRequests()` query to find entities that have a small number of pull requests opened in the last two weeks:

```
git.pullRequests(lookback=duration("P14D")).length < 3
```

This can highlight entities that haven't been updated recently, which may be especially useful when entities have to be updated to address a vulnerability.

</details>

<details>

<summary>Reviews</summary>

List reviews left during a defined lookback period.

* Organization
* Repository
* Review date
* Reviewer

**Definition:** `git.reviews()`

**Examples**

A development maturity Scorecard might use the `git.reviews()` expression to make sure that there is a rigorous review process in place before changes are implemented:

```
git.reviews(lookback=duration("P7D")).length > 25
```

This rule makes sure that there are more than 25 reviews left in the last week.

</details>

<details>

<summary>Workflow runs</summary>

Get workflow runs meeting given filter criteria, including conclusions, statuses, and a lookback period.

* Conclusion
* Name
* Run started at
* Run time
* Run updated at
* Status

Conclusions: `FAILURE`, `SUCCESS`, `TIMED_OUT`

Statuses: `QUEUED`, `IN_PROGRESS`, `COMPLETED`

The lookback period specifies a duration for which returned runs should be created within, defaulting to a period of 3 days.

* The `runTime` of the `WorkflowRun` object represents the difference between `runStartedAt` and `runUpdatedAt` times in seconds.

**Definition:** `git.workflowRuns()`

**Example**

To make sure an entity has had a successful workflow run within the last two weeks, you can write a rule like:

```
git.workflowRuns(conclusions=["SUCCESS"], statuses=["COMPLETED"], lookback=duration("P14D")).length > 0
```

This rule is checking for GitHub workflow runs with a `SUCCESS` conclusion and `COMPLETED` status during a 14-day lookback window.

</details>

**Ownership CQL**

<details>

<summary>All ownership details</summary>

A special built-in type that supports a null check or a count check, used to enforce ownership of entities.

**Definition:** `ownership: Ownership | Null`

**Example**

An initial level in a security Scorecard might include a rule to ensure an entity has at least one team as an owner:

```
ownership.teams().length > 0
```

</details>

<details>

<summary>All owner details</summary>

List of owners, including team members and individual users, for each entity

**Definition:** `ownership.allOwners()`

**Example**

The Scorecard might include a rule to ensure that entity owners all have an email set:

```
ownership.allOwners().all((member) => member.email != null)
```

</details>

<details>

<summary>Team details</summary>

List of teams for each entity

**Definition:** `ownership.teams(): List<Team>`

**Example**

The Scorecard might include a rule to ensure that an entity owners all have a description and are not archived:

```
ownership.teams().all(team => team.description != null and team.isArchived == false)
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex conducts a background sync of GitLab identities every day at 10 a.m. UTC. Merge requests are refreshed every 2 minutes.

## FAQ and Troubleshooting

**Why is my CQL query `git.branchProtection()` returning no results or a 403 error?**

This can happen if you do not have the `read_api` scope set for your access token, or if the GitLab user who generated the token does not have at minimum the `Maintainer` role.

**Why isn't Cortex pulling in user emails from GitLab (identity mapping / team members missing emails)?**

Email addresses are treated as sensitive user identity data in GitLab, not project data, so a `Maintainer`-level token isn't sufficient in most modern GitLab environments, especially enterprise instances with SSO or stricter privacy controls. Use a token created by an `Owner` or `Admin` user with the `api` (or `read_user`) scope.

Note that `Maintainer` tokens *may* work on loosely configured self-managed instances, but this is not reliable. Email visibility also depends on instance configuration and individual user privacy settings (e.g., hidden emails).

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Google

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

## Overview

[Google Workspace](https://workspace.google.com/) is an ownership and cloud resources platform.

Integrating Cortex with Google allows you to:

* Automatically discover and track ownership of [Google entities](#supported-google-entity-types)
* Pull in Service Level Objectives (SLOs) from Google Cloud Observability, and [view this information on entity pages](#view-google-cloud-observability-data-in-entity-pages)
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your Google resources and teams

{% hint style="info" %}
For information on configuring Google SSO for logging in to Cortex, see the [Google SSO documentation](/configure/settings/managing-users/configuring-sso).
{% endhint %}

## How to configure Google with Cortex

### Prerequisites

Before getting started:

#### Prerequisite 1: Configure a Google service account and copy its client ID.

Create a [Google service account](https://cloud.google.com/iam/docs/service-accounts).

* In the Advanced settings, enable **Domain-wide Delegation**.
* Under the Domain-wide Delegation setting, copy the client ID and store it in a secure location; you will need this in the next steps.

The service account should have the following permissions for each project to enable Google Cloud resources:

<details>

<summary><strong>Google service account permissions</strong></summary>

* AI Platform → AI Platform Viewer, Dataform Viewer, Cloud Storage for Firebase Viewer, Data Catalog Viewer, Vision AI Viewer, Notebooks Viewer, Dataflow Viewer
* Apigee → Cloud Api Hub Viewer
* App Engine → App Engine Viewer
* Artifact Registry → Artifact Registry Reader
* BigQuery → BigQuery Metadata Viewer
* BigQuery Connection → BigQuery Connection User
* Cloud Asset → Cloud Asset Viewer
* Cloud Asset → ListResource
  * Note: This permission is necessary to run services and jobs.
* Cloud Functions → Cloud Functions Viewer
* Cloud Pub/Sub → Pub/Sub Viewer
* Cloud Resource Manager → Browser
* Cloud Run → Cloud Run Viewer
* Cloud SQL → Cloud SQL Viewer
* Cloud Storage → Storage Admin
* Composer → Composer User
* Compute Engine, VM Instances → Compute Viewer
* Kubernetes Engine → Kubernetes Engine Viewer
* Memorystore Memcached → Cloud Memorystore Memcached Viewer
* Memorystore Redis → Cloud Memorystore Redis Viewer
* Monitoring → Monitoring Viewer
* Service Accounts → View Service Accounts
* Spanner → Cloud Spanner Viewer
* VM Instances Vulnerabilities → OS VulnerabilityReport Viewer
* VPC Serverless Connector → Serverless VPC Access Viewer

</details>

If you'd like to create a custom role with the minimum permissions required to enable this feature, add the following:

<details>

<summary>Custom role minimum permissions</summary>

```
aiplatform.datasets.get
aiplatform.datasets.list

aiplatform.endpoints.get
aiplatform.endpoints.list

aiplatform.featurestores.get
aiplatform.featurestores.list

aiplatform.indexEndpoints.get
aiplatform.indexEndpoints.list

aiplatform.batchPredictionJobs.get
aiplatform.batchPredictionJobs.list

aiplatform.modelDeploymentMonitoringJobs.get
aiplatform.modelDeploymentMonitoringJobs.list

aiplatform.trainingPipelines.get
aiplatform.trainingPipelines.list

aiplatform.pipelineJobs.get
aiplatform.pipelineJobs.list

aiplatform.specialistPools.get
aiplatform.specialistPools.list

aiplatform.tensorboardExperiments.get
aiplatform.tensorboardExperiments.list

aiplatform.studies.get
aiplatform.studies.list

aiplatform.apps.get
aiplatform.apps.list

aiplatform.indexes.get
aiplatform.indexes.list

aiplatform.models.get
aiplatform.models.list

aiplatform.tensorboards.get
aiplatform.tensorboards.list

iam.serviceAccounts.get

apihub.apiHubInstances.get

apihub.apis.get
apihub.apis.list

appengine.services.get
appengine.services.list

artifactregistry.repositories.get
artifactregistry.repositories.list

bigquery.connections.get
bigquery.connections.list

bigquery.datasets.get
bigquery.routines.get
bigquery.routines.list

cloudasset.assets.listResource

cloudfunctions.functions.get
cloudfunctions.functions.list

cloudsql.instances.get
cloudsql.instances.list

composer.environments.get
composer.environments.list

compute.urlMaps.list
compute.urlMaps.get
compute.instances.list
compute.instances.get
compute.instanceGroups.list
compute.instanceGroups.get

container.clusters.get
container.clusters.list

container.operations.get
container.operations.list

iam.serviceAccounts.get
iam.serviceAccounts.list

memcache.instances.list
memcache.instances.get

monitoring.services.get
monitoring.services.list
monitoring.slos.get
monitoring.slos.list
monitoring.timeSeries.list

notebooks.instances.get
notebooks.instances.list

osconfig.vulnerabilityReports.get

pubsub.topics.get
pubsub.topics.list

redis.instances.list
redis.instances.get

resourcemanager.projects.get
resourcemanager.projects.list

run.jobs.list
run.jobs.get

run.services.list
run.services.get

spanner.instances.get
spanner.instances.list

spanner.instanceConfigs.get
spanner.instanceConfigs.list

storage.buckets.get
storage.buckets.list

visionai.applications.get
visionai.applications.list

visionai.processors.get
visionai.processors.list

visionai.operators.get
visionai.operators.list

visionai.clusters.get
visionai.clusters.list

vpcaccess.connectors.get
vpcaccess.connectors.list

```

</details>

#### Prerequisite 2: Configure Google Admin SDK API

Enable the [Google Admin SDK API](https://console.developers.google.com/apis/api/admin.googleapis.com/overview).

#### Prerequisite 3: Configure Google Cloud resource project permissions

* For Google Cloud resources, in each project, enable the following:

<details>

<summary>Google Cloud resources project permissions</summary>

* [App Engine Admin API](https://console.cloud.google.com/marketplace/product/google/appengine.googleapis.com)
* [ArtifactRegistry API](https://console.cloud.google.com/marketplace/product/google/artifactregistry.googleapis.com)
* [Apigee APIs](https://console.cloud.google.com/marketplace/product/google/apigee.googleapis.com)
* [BigQuery API](https://console.cloud.google.com/marketplace/product/google/bigquery.googleapis.com)
* [BigQuery Connection API](https://console.cloud.google.com/marketplace/product/google/bigqueryconnection.googleapis.com)
* [Cloud Asset API](https://console.cloud.google.com/marketplace/product/google/cloudasset.googleapis.com)
* [Cloud Composer API](https://console.cloud.google.com/marketplace/product/google/composer.googleapis.com)
* [Cloud Functions](https://console.cloud.google.com/marketplace/product/google/cloudfunctions.googleapis.com)
* [Cloud SQL Admin](https://console.cloud.google.com/marketplace/product/google/sqladmin.googleapis.com)
* [Cloud Storage](https://console.cloud.google.com/marketplace/product/google/storage.googleapis.com)
* [Compute Engine API](https://console.cloud.google.com/marketplace/product/google/compute.googleapis.com)
* [Kubernetes Engine API](https://console.cloud.google.com/marketplace/product/google/container.googleapis.com)
* [Memorystore for Memcached API](https://console.cloud.google.com/marketplace/product/google/memcached.googleapis.com)
* [Memorystore for Redis API](https://console.cloud.google.com/marketplace/product/google/redis.googleapis.com)
* [OS Config API](https://console.cloud.google.com/marketplace/product/google/osconfig.googleapis.com)
* [Kubernetes Engine API](https://console.cloud.google.com/marketplace/product/google/container.googleapis.com)
* [Resource Manager API](https://console.cloud.google.com/marketplace/product/google/cloudresourcemanager.googleapis.com)
* [Spanner API](https://console.cloud.google.com/marketplace/product/google/spanner.googleapis.com)
* [Serverless VPC Access API](https://console.cloud.google.com/marketplace/product/google/vpcaccess.googleapis.com)

</details>

* For each project in Vertex AI, enable the following:
  * [Cloud Storage API](https://console.cloud.google.com/marketplace/product/google/storage-component.googleapis.com)
  * [DataCatalog API](https://console.cloud.google.com/marketplace/product/google/datacatalog.googleapis.com)
  * [Dataflow AI API](https://console.cloud.google.com/marketplace/product/google/dataflow.googleapis.com)
  * [DataForm API](https://console.cloud.google.com/marketplace/product/google/dataform.googleapis.com)
  * [Notebooks AI API](https://console.cloud.google.com/marketplace/product/google/notebooks.googleapis.com)
  * [Vertex AI API](https://console.cloud.google.com/marketplace/product/google/aiplatform.googleapis.com)
  * [Vision AI API](https://console.cloud.google.com/marketplace/product/google/visionai.googleapis.com)

### Step 1: Configure the integration in Google

1. In the [G Suite admin console](https://admin.google.com/), navigate to **Security > API Controls > Manage Domain Wide Delegation**. Click **Add new**.
2. Add the client ID you obtained in [Prerequisite 1](#prerequisite-1-configure-a-google-service-account-and-copy-its-client-id), and include the following scopes:
   * `https://www.googleapis.com/auth/admin.directory.group.readonly`
   * `https://www.googleapis.com/auth/admin.directory.group.member.readonly`
3. Navigate to the service account you created for this integration. Click **Keys**, then generate a key in JSON format.
4. Navigate to **Admin Roles > Groups Reader** and expand the "Admins" panel.
5. Click **Assign service accounts** then enter the email of the service account you created for this integration.

### Step 2: Configure the integration in Cortex

1. In Cortex, navigate to the [Google settings page](https://app.getcortexapp.com/admin/integrations/google):
   * Click **Integrations** from the main nav. Search for and select **Google**.
2. Click **Add configuration**.
3. Configure the Google integration form:
   * **Domain**: Enter your Google domain.
   * **Service account email**: Enter the email address for the service account.
   * **Credentials JSON**: Enter the service account JSON key you created in the previous steps.
4. Click **Save**.

By default, a service will have dependencies on any resource with Google Cloud tag label = "service" and tag value = the service's Cortex tag. After saving your integration, you may customize the tag key name here by entering a new name into the **Custom label key** field. Leave it blank to use "service" as the key name.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## Supported Google entity types

Cortex supports pulling in the following entity types from Google:

<details>

<summary>Supported Google entity types</summary>

* Google Cloud Vertex AI Batch Prediction Job
* Google Cloud Vertex AI Dataset
* Google Cloud Vertex AI Endpoint
* Google Cloud Vertex AI Featurestore
* Google Cloud Vertex AI Index
* Google Cloud Vertex AI Model
* Google Cloud Vertex AI Model Deployment Monitoring Job
* Google Cloud Vertex AI Notebooks Instance
* Google Cloud Vertex AI Pipeline Job
* Google Cloud Vertex AI Platform Index Endpoint
* Google Cloud Vertex AI Specialist Pool
* Google Cloud Vertex AI Study
* Google Cloud Vertex AI Tensorboard
* Google Cloud Vertex AI Training Pipeline
* Google Cloud Vertex AI Vision Application
* Google Cloud Vertex AI Vision Cluster
* Google Cloud Vertex AI Vision Index Point
* Google Cloud Vertex AI Vision Operator
* Google Cloud Vertex AI Vision Processor
* Google Cloud Apigee Api
* Google Cloud Apigee Instance
* Google Cloud App Engine Service
* Google Cloud Artifact Registry Repository
* Google Cloud BigQuery Connection
* Google Cloud BigQuery
* Google Cloud Composer Environment
* Google Cloud Functions
* Google Cloud Kubernetes Engine Clusters
* Google Cloud Kubernetes Engine Operations
* Google Cloud IAM Service Account
* Google Cloud Instance Group
* Google Cloud HTTP(S) Load Balancing
* Google Cloud Memorystore Memcached
* Google Cloud Memorystore Redis
* Google Cloud Project
* Google Cloud Run Job
* Google Cloud Run Service
* Google Cloud Spanner Instance
* Google Cloud Spanner Instance Config
* Google Cloud SQL
* Google Cloud Storage
* Google Cloud Pub/Sub Topics
* Google Cloud VM Instances
* Google Cloud VPC Serverless Connector

</details>

## How to connect Cortex entities to Google

### Enable automatic import of Google entities

You can configure automatic import from Google Cloud. Note that this setting does not include team entities.

1. In Cortex, navigate to [**Settings > Entities > General**](https://app.getcortexapp.com/admin/settings/entities/general).
2. Next to **Auto import from AWS, Azure, and/or Google Cloud**, click the toggle to enable the import.\\

   <figure><img src="/files/p4fNmdV0qFSbUMX1YwGD" alt=""><figcaption></figcaption></figure>

### Import teams from Google

See the [Create teams documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams#creating-a-team) for instructions on importing entities.

### Automatic ownership of Google entities

Cortex can use Google Groups as an ownership provider, automatically syncing memberships from any Google Group mailing list.

### Automatic Google dependency discovery

By default, Cortex will try to automatically discover dependencies between your entities and Google Cloud resources with a matching label. By default the label key that will be matched is `service`, however you can customize this key value in the Google Cloud [Settings page](https://app.getcortexapp.com/admin/settings/google-cloud-and-groups).

If you'd like to explicitly define these Google Cloud dependencies, the `x-cortex-dependency` field should be a map, defined as follows:

```yaml
x-cortex-dependency:
   gcp:
     labels:
       - key: my-key-1
         value: my-value-1
       - key: my-key-2
         value: my-value-2
```

### Editing the entity descriptor

#### Groups

```yaml
x-cortex-owners:
  - type: group
    name: my-group-email@getcortexapp.com
    provider: GOOGLE
    description: This is a description for this owner # optional
```

The value for `name` should be the *full group email* as defined in Google Groups.

#### Entities

Cortex uses the resource name and project ID to look up catalog entities in your Google Cloud account. Function resource names should be of the format `location/function`

```yaml
x-cortex-infra:
  Google Cloud:
    resources:
      - resourceName: location/function
        projectId: project1
        resourceType: function
      - resourceName: example-bucket
        projectId: project1
        resourceType: storage
```

#### SLOs

```yaml
x-cortex-slos:
    gcp:
      - projectId: cortex-gcp-integration
        serviceId: iLE2e4HvR_iVlxAaBbCc12
      - projectId: cortex-gcp-integration
        serviceId: adfdfdafd
```

The `serviceID` value is the value of the Unique ID listed on the [service page in Google Cloud Observability](https://console.cloud.google.com/monitoring/services).

## Using the Google integration

### View Google Cloud Observability data in entity pages

After integrating with Google, you will see data from Google Cloud Observability on [entity details pages](/ingesting-data-into-cortex/entities-overview/entities/details):

* On an entity's overview page, see an overview of SLOs for the entity.
* Click **Monitoring > Google** in an entity's sidebar to see more information about Google SLOs, including the SLO name, its targets, its status, the current value for that entity, and the period of time the SLO is being calculated for. For example, if the time listed is "7 days ago," then the SLO is looking at the time range starting 7 days ago to now.

### Scorecards and CQL

With the Google integration, you can create Scorecard rules and write CQL queries based on GCP details, Google Cloud Observability SLOs, and Google teams.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>GCP details</summary>

Get the GCP details for the entity.

**Definition:** `gcp.details()`

**Examples**

A Scorecard might include a rule to verify that an entity has GCP details:

```
gcp.details() != null
```

You might include a rule to check whether any labels on the GCP recourse are titled `origin`:

```
jq(gcp.details(), ".resources[0].labels | any(\"origin\")")
```

</details>

<details>

<summary>SLOs</summary>

SLOs associated with the entity via ID or tags. You can use this data to check whether an entity has SLOs associated with it, and if those SLOs are passing.

**Definition:** `slos: List<SLO>`

**Example**

In a Scorecard, you can use this expression to make sure an entity is passing its SLOs:

```
slos().all((slo) => slo.passing) == true
```

Use this expression to make sure latency Service Level Indicator (SLI) value is above 99.99%:

```
slos().filter((slo) => slo.name.matchesIn("latency") and slo.sliValue >= 0.9999).length > 0
```

</details>

**Ownership CQL**

<details>

<summary>All ownership details</summary>

A special built-in type that supports a null check or a count check, used to enforce ownership of entities.

**Definition:** `ownership: Ownership | Null`

**Example**

An initial level in a security Scorecard might include a rule to ensure an entity has at least one team as an owner:

```
ownership.teams().length > 0
```

</details>

<details>

<summary>All owner details</summary>

List of owners, including team members and individual users, for each entity

**Definition:** `ownership.allOwners()`

**Example**

The Scorecard might include a rule to ensure that entity owners all have an email set:

```
ownership.allOwners().all((member) => member.email != null)
```

</details>

<details>

<summary>Team details</summary>

List of teams for each entity

**Definition:** `ownership.teams(): List<Team>`

**Example**

The Scorecard might include a rule to ensure that an entity owners all have a description and are not archived:

```
ownership.teams().all(team => team.description != null and team.isArchived == false)
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex conducts an ownership sync for Google teams every day at 9 a.m. UTC.

## Troubleshooting and FAQ <a href="#still-need-help" id="still-need-help"></a>

#### The GCP integration only supports a single service account. Can I work around this?

By default, GCP service accounts are restricted to the project they were created in. If other projects don’t explicitly allow that service account to access their resources, Cortex can’t collect data from them. To work around this, you can configure a principal service account and associate it with multiple projects in GCP. Once the service account is linked to other projects, Cortex can use that service account to pull data from multiple GCP projects.

After creating a service account that is linked to a project, open your second project in GCP and go to **IAM & Admin > IAM >** Click **+Add**. Using the service account ID that you already created, add a principal to the project. Repeat these steps for each project.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Grafana

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Grafana](https://grafana.com/) is an open-source observability platform that provides monitoring and visual analytics for application performance. Use Grafana to [visualize](https://grafana.com/docs/grafana/latest/panels-visualizations/visualizations/) your data, from bar charts and histograms to pie charts and geomaps.

Integrating Grafana with Cortex allows you to:

* [View Grafana charts on entity pages](#viewing-grafana-graphs-on-an-entity) in Cortex
* Create [Scorecards](#scorecards-and-cql) that include rules related to Grafana dashboards

## How to configure Grafana with Cortex

### Prerequisites

Before getting started:

* Your Grafana dashboard must have [`allow_embedding` enabled](https://grafana.com/docs/grafana/next/setup-grafana/configure-grafana/#allow_embedding).
* Your [Grafana dashboard must be public](https://grafana.com/docs/grafana/latest/dashboards/share-dashboards-panels/shared-dashboards/) OR if you are on a [Self-managed Cortex](/self-managed) instance, then Cortex and Grafana must be accessible within the same private network (such as a VPN).
  * You will need the public embed link provided in the iframe snippet.

### Embed the chart in an entity's YAML file

Define the public embed link in the [entity descriptor YAML](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file) for each entity where you want to embed a chart.

1. For the entity where you want to embed a chart, open its YAML file.
   * You can do this locally if following a [GitOps](/configure/gitops) approach, or you can edit a YAML file directly in the Cortex UI on the [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details).
2. Add the `x-cortex-dashboards` block. Include the `type` (`grafana`) and the `url` (the public embed link you obtained from Grafana). See the example below:

```yaml
x-cortex-dashboards:
  embeds:
    - type: grafana
      url: https://snapshots.raintank.io/dashboard-solo/snapshot/y7zwi2bZ7FcoTlB93WN7yWO4aMiz3pZb?from=1493369923321&to=1493377123321&panelId=4&orgId=0
```

| Field  | Description                             | Required |
| ------ | --------------------------------------- | :------: |
| `type` | Type of embed (in this case, `grafana`) |   **✓**  |
| `url`  | Embed URL for the Grafana dashboard     |   **✓**  |

Repeat the steps above for each entity you want to add a Grafana chart to.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## Using the Grafana integration

### Viewing Grafana charts on an entity

Once you've defined the chart in an entity's YAML, you can view the graphs from an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details).

In an entity's sidebar, click **Dashboard**. All charts defined in the entity descriptor will be embedded on this page.

### Scorecards and CQL

With the Grafana integration, you can create Scorecard rules and write CQL queries based on Grafana charts.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Embeds</summary>

Query against embeds associated with an entity.

**Definition:** `embeds()`

**Example**

If Grafana charts are a core part of operations at your organization, you can set a Scorecard rule to make sure entities have embedded charts.

```
embeds().any((embed) => embed.type == "GRAFANA")
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Grafana charts are updated in real time.

## FAQs and troubleshooting

**I've correctly added the embed URL, but the graph is showing an error or a blank screen.**

You may need to [enable embedding](https://grafana.com/docs/grafana/latest/administration/configuration/#allow_embedding) in your Grafana instance.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Humanitec

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Humanitec](https://humanitec.com/) offers products to build on top of your Engineering Operations Platform for containerized workloads.

Integrating Humanitec with Cortex allows you to run a Humanitec pipeline directly from Cortex.

## How to integrate Humanitec with Cortex

### Prerequisites

Before getting started:

* You should have an app with a working pipeline configured in Humanitec.
* Create a service user in Humanitec, and create an [API token in Humanitec](https://developer.humanitec.com/platform-orchestrator/docs/platform-orchestrator/reference/api-references/#authentication) for the service user.

### Step 1: Create a Workflow in Cortex

1. Follow the instructions to [begin creating a Workflow](/streamline/workflows/create#step-1-choose-a-template-or-a-blank-workflow) and [configure its basic settings](/streamline/workflows/create#step-2-configure-your-workflow-settings).
2. Add an **HTTP request** block to your Workflow. Configure the block:
   * **Block name**: Enter a descriptive name for the block.
   * **Slug**: Enter a unique identifier for the block.
   * **HTTP method**: Select `POST`.
   * **URL**: Enter a Humanitec API URL based on the Humanitec call [`createPipelineRun`](https://api-docs.humanitec.com/#tag/PipelineRuns/operation/createPipelineRun), e.g., `https://api.humanitec.io/orgs/<your-Humanitec-org>/<your-app-ID>/pipelines/<pipeline-ID>/runs`
3. At the bottom of the side panel, click **Save**.
4. Make any other necessary changes to your Workflow, then in the upper right corner of the page, click **Save workflow**.

Alternatively, you can also use an **Async HTTP request** block in your Workflow, using the [Humanitec action `actions/humanitec/http@v1`](https://developer.humanitec.com/platform-orchestrator/docs/integration-and-extensions/humanitec-pipelines/available-actions/#actionshumanitechttpv1) to call back to Cortex.

### Step 2: Run the Workflow

* At the top of your Workflow in Cortex, click **Run**.

In your Humanitec workspace under your app's pipelines, you will see the run listed under the **Runs** tab:

<figure><img src="/files/n9o0b2AVLD81anbB0Bcx" alt="Runs are listed in Humanitec under the app&#x27;s pipeline runs tab."><figcaption></figcaption></figure>

## Example using Cortex with AWS, Humanitec, and Terraform

See the video below where a member of the Humanitec team walks through advanced end-to-end setup on AWS using Cortex, Humanitec as the orchestrator, and Terraform modules deployed via ECS runners. The video demonstrates detecting a policy violation and remediating it.

{% embed url="<https://www.youtube.com/watch?t=44s&v=iFYO0TFF5cs>" %}


# incident.io

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[incident.io](https://incident.io/) is an incident management and alerting platform.

Integrating incident.io with Cortex allows you to:

* [Trigger an incident](#trigger-an-incident) directly from Cortex
* View incident data on entity pages in Cortex
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving incidents

## How to configure incident.io with Cortex

### Prerequisites

Before getting started:

* Create an [incident.io API key](https://app.incident.io/settings/api-keys) with the following scopes:
  * **Create incidents**
  * **View all incident data**, including private incidents
  * **View data** like public incidents and organization settings
  * **View catalog** types and entries

### Configure the integration in Cortex

1. In Cortex, navigate to the [incident.io settings page](https://app.getcortexapp.com/admin/integrations/incidentio):
   * Click **Integrations** from the main nav. Search for and select **incident.io**.
2. Click **Add configuration**.
3. Configure the incident.io integration form:
   * **Account alias**: Enter the alias for your configuration.
   * **API key**: Enter your incident.io API key.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

**Configure the integration for multiple incident.io accounts**[**​**](https://docs.cortex.io/docs/reference/integrations/incidentio#configure-the-integration-for-multiple-propsintegration-accounts)

The incident.io integration has multi-account support. You can add a configuration for each additional instance by repeating the process above.

Each configuration requires an alias, which Cortex uses to correlate the designated instance with registrations for various entities. Registrations can also use a default configuration without a listed alias. You can edit aliases and default configurations from the incident.io page in your Cortex settings. Select the edit icon next to a given configuration and toggle **Set as default** on. If you only have one configuration, it will automatically be set as the default.

## How to connect Cortex entities to incident.io

### Discovery

By default, Cortex will try to "best-guess" the corresponding custom field value in incident.io for all catalog-based custom fields.

Cortex first looks up a custom field values using the name (e.g. `My Entity`), then the entity identifier (e.g. `my-entity`). For example, if your entity name is "My Entity," then the corresponding custom tag field in incident.io should either be "My Entity" or "my-entity."

### Editing the entity descriptor

```yaml
x-cortex-incident-io:
  customFields:
  - name: Entity
    value: My Entity
    alias: my-default-alias
```

| Field   | Description                                                                                      | Required |
| ------- | ------------------------------------------------------------------------------------------------ | :------: |
| `name`  | Name for the entity (from `customFieldName`)                                                     |   **✓**  |
| `value` | Display name for the entity in Cortex                                                            |   **✓**  |
| `alias` | Alias for the configuration in Cortex (only needed if you have opted into multi-account support) |          |

```yaml
x-cortex-incident-io:
  customFields:
  - id: Entity_ID
    value: my-second-entity
    alias: my-other-alias
```

| Field   | Description                                                                                      | Required |
| ------- | ------------------------------------------------------------------------------------------------ | :------: |
| `id`    | ID for the entity (from `customFieldID`)                                                         |   **✓**  |
| `value` | Tag for the entity in Cortex                                                                     |   **✓**  |
| `alias` | Alias for the configuration in Cortex (only needed if you have opted into multi-account support) |          |

## Using the incident.io integration

### View incident.io information on entity pages

Once the integration is set up, incident data will appear on [entity details pages](/ingesting-data-into-cortex/entities-overview/entities/details).

Active incidents detected in incident.io will appear on an entity's details page in the **Operations** block under the **Overview** tab. More detailed information is also available under the **Operations** tab.

Incident data will also be pulled into the incident.io page under the **On-call & incidents** page in the entity's sidebar.

### Trigger an incident

While viewing an entity in Cortex, you can trigger an incident in incident.io:

1. In Cortex, navigate to an entity. On the left side of an entity details page, click **On-call & incidents.**
2. In the upper right side of the entity's "On-call" page, click **Trigger incident**.
3. Configure the incident modal:
   * **Summary**: Enter a title for the incident.
   * **Description**: Enter a description of the incident.
   * **Severity**: Select a severity level.
4. At the bottom of the modal, click **Trigger incident**.
   * A confirmation screen will appear. In the confirmation, click the link to view the incident in incident.io.

### Scorecards and CQL

With the incident.io integration, you can create Scorecard rules and write CQL queries based on incident.io incidents.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if incident.io service is set</summary>

Check if entity has a registered incident.io custom field value in its entity descriptor.

If no registration exists, Cortex will try to automatically detect which corresponding incident.io custom field value is associated with the entity.

**Definition:** `incidentio (==/!=) null`

**Example**

For a Scorecard focused on operational maturity, you can use this expression to make sure each entity has an incident.io project set:

```
incidentio != null
```

</details>

<details>

<summary>Incidents</summary>

List incidents, filterable by severity and status.

* Created at
* Mode
* Name
* Severity
* Status
* Summary
* Type
* URL

**Definition:** `incidentio.incidents()`

**Examples**

To assess entities' health in a Scorecard, you can write a rule to make sure a given entity has fewer than three incidents with a severity of SEV1:

```
incidentio.incidents(severity = ["SEV1"]).length < 3
```

You can also use this expression to query for entities that have two or fewer critical incidents in the last three months:

```
  incidentio.incidents(severity = ["Critical"]).filter((incident) => incident.createdAt.fromNow() > duration("-P90D")).length <= 2
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Instana

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

## Overview

[IBM Instana Observability](https://www.ibm.com/products/instana) is a tool used for monitoring and performance management. Integrate Instana with Cortex allows you to pull in services from Instana.

## How to configure Instana with Cortex

### Prerequisite

Before getting started, [create an API token in Instana](https://www.ibm.com/docs/en/instana-observability/current?topic=api-authenticating-instana-rest).

### Configure the integration in Cortex

1. In Cortex, navigate to the [Instana settings page](https://app.getcortexapp.com/admin/integrations/instana):
   1. Click **Integrations** from the main nav. Search for and select **Instana**.
2. Click **Add configuration**.
3. Configure the Instana integration form:
   * **Tenant endpoint**: Enter your tenant endpoint. This can be found in your Instana app URL.
   * **API token**: Enter the API token you generated in Instana.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Instana

### Import services from Instana

Cortex automatically syncs from Instana APM at 7 a.m. UTC.

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on importing entities.

### Import Instana services from Discovery audit

Cortex will pull recent changes from Instana into the [discovered entities list](/ingesting-data-into-cortex/entities-overview/entities/discovery-audit). Here, you can find new entities in Instana that have not been imported into the catalog.

## View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Jenkins

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Jenkins](https://www.jenkins.io/) is an open source automation server which enables developers to build, test, and deploy software.

Integrating Jenkins with Cortex allows you to:

* Send information about Jenkins deploys into Cortex
  * This data appears on [entity detail pages](#view-jenkins-deploys-on-entity-pages-in-cortex).
* Use [Cortex Workflows to kick off a Jenkins pipeline](#kick-off-a-jenkins-pipeline-in-a-cortex-workflow)
* See [deploy data for Jenkins in Eng Intelligence](#see-jenkins-data-in-eng-intelligence)

## How to integrate Jenkins with Cortex

### Prerequisites

Before getting started:

* Create a [Jenkins API key](https://www.jenkins.io/doc/book/system-administration/authenticating-scripted-clients/).
  * Note: This is only necessary if you plan to use Jenkins blocks in Cortex Workflows.

### Step 1: Install the Cortex Deployer app

This integration uses the Cortex Deployer app, an open-source app that makes it easier for teams to push information about deploys to Cortex. This app leverages Cortex's [deploy REST endpoint](/api/readme/deploys).

* Install the [Cortex Deployer app](https://github.com/cortexapps/solutions/tree/master/tools/deploy).

### Step 2: Add a step to your Jenkins pipeline

#### Jenkins secrets

To use the Cortex Deployer app, you will need the `x-cortex-tag` and a Cortex API token. In the example below, both are defined as [Jenkins secrets](https://www.jenkins.io/doc/developer/security/secrets/).

#### Jenkinsfile

To push information to Cortex about a deploy event, add a step to your Jenkins pipeline. Below is a snippet of what a Jenkinsfile may look like.

```
pipeline {
    agent any
    environment 
    stages {
        stage('update-cortex') { 
            steps {
                sh "docker run cortexapp/deployer:0.2 -i \"Jenkins deploy\" -k $CORTEX_API_TOKEN -s $GIT_COMMIT -t DEPLOY -e Prod -c '' -g $CORTEX_TAG" 
            }
        }
    }
}
```

For more details about the options passed to the Docker image, please refer to the [Deployer repository](https://github.com/cortexapps/solutions/tree/master/tools/deploy).

### Step 3: Configure Jenkins in Cortex to enable Jenkins Workflow blocks <a href="#still-need-help" id="still-need-help"></a>

If you plan to use Jenkins blocks in Cortex Workflows, you will need to configure Jenkins in your Cortex workspace:

1. In Cortex, navigate to the [Jenkins settings page](https://app.getcortexapp.com/admin/integrations/jenkins):
   * Click **Integrations** from the main nav. Search for and select **Jenkins**.
2. Click **+Add configuration**.
3. Configure the integration form:
   * **Alias**: Enter an alias for the integration.
   * **Username**: Enter your Jenkins username.
   * **API key**: Enter your Jenkins API key.
   * **Host**: Enter the base URL of your Jenkins instance.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## Using the Jenkins integration <a href="#still-need-help" id="still-need-help"></a>

### View Jenkins deploys on entity pages in Cortex

After you configure the integration, you will see data about Jenkins deploys in an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details):

* On the entity overview, Jenkins deploys will appear under the **Latest events** section.
* In the entity's sidebar, click **Events** to see a full list of events for the entity, including deploy events from Jenkins.
* In the entity's sidebar, click **CI/CD > Deploys** to see data from the [Cortex deploys API](/api/readme/deploys), including Jenkins deploys.

### Kick off a Jenkins pipeline in a Cortex Workflow

You can use a Workflow to kick off a Jenkins pipeline. [See this docs page for more information](https://github.com/cortexapps/hippocampus/blob/master/ingesting-data-into-cortex/integrations/broken-reference/README.md).

### See Jenkins data in Eng Intelligence

Since the Jenkins integration uses Cortex's [deploys API endpoint](/api/readme/deploys), Jenkins data is included in Eng Intelligence deploy metrics. Learn more about [Eng Intelligence in the docs](/improve/eng-intelligence).

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Jira

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Jira](https://www.atlassian.com/software/jira/guides/getting-started/introduction) is a project management tool that helps developers track and manage bugs and work items.

By integrating Jira with Cortex, you can drive improvements and coordinate issue management across teams. Through the integration, you can create Jira work items directly in Cortex based on an Initiative's action items. The integration also allows you to enhance insights into a number of key values for your entities:

* Customer facing incidents
* Security tickets
* Ongoing projects

## How to configure Jira with Cortex

It is possible to configure the integration with a Jira Cloud instance or a self-hosted Jira instance (using either basic auth or OAuth). You can also use Cortex Axon Relay to securely integrate your on-premises data. See the tabs below for instructions on each option.

{% tabs %}
{% tab title="Jira Cloud" %}
**Jira Cloud**

**Prerequisites**

Before configuring Cortex with Jira Cloud:

* Create a [Jira API token](https://id.atlassian.com/manage-profile/security/api-tokens). To generate a token, you must have the `Browse users and groups` permissions in Jira and access to the needed Jira projects.
* If you are using a scoped token, you will need your [Atlassian Cloud ID](https://support.atlassian.com/jira/kb/retrieve-my-atlassian-sites-cloud-id/). Scoped tokens must include the following scopes:
  * Read: `jira-work`, `jira-user`, `project-category:jira`, `project:jira`, `project-version:jira`, `project.property:jira`, `project.component:jira`, `issue-type:jira`, `issue-type-hierarchy:jira`, `user:jira`, `avatar:jira`, `project.avatar:jira`, `application-role:jira`, `group:jira`
  * Write: `jira-work`

**Configure the integration in Cortex**

1. In Cortex, navigate to the [Jira settings page](https://app.getcortexapp.com/admin/integrations/jira):
   * Click **Integrations** from the main nav. Search for and select **Jira**.
2. Click **Add configuration**. then select **Cloud** for the integration type.
   * If you are using a scoped token, select **Cloud (scoped token)**.
3. In the Jira integration modal, "Jira Cloud" is selected by default in the upper right corner. Configure the integration form:
   * **Account alias**: Enter an alias for your account.
   * **Subdomain**: Enter the subdomain for your Jira instance.
     * For example, this field would take `cortex-docs` from `https://cortex-docs.atlassian.net`.
   * **Base URL**: This field automatically populates `atlassian.net`.
     * If you are using a legacy Jira Cloud instance (i.e., you access your Jira instance on `jira.com`), change the base URL from the dropdown.
   * **Email**: Enter the email address associated with the user who generated the token in Jira.
     * Note: The email address associated with a given Jira token **must** match the email address of the user associated with that token.
   * **API token**: Enter your Jira API token.
4. Click **Save**.
   {% endtab %}

{% tab title="On-prem (Basic)" %}
**Jira on-prem (Basic)**

**Prerequisite**

If you're using a self-hosted instance of Jira, you'll need to verify that your Cortex instance is able to reach the Jira instance.\
\
We route our requests through a static IP address. Reach out to support at <help@cortex.io> to receive details about our static IP. If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your Jira instance.

**Configure the integration in Cortex**

1. In Cortex, navigate to the [Jira settings page](https://app.getcortexapp.com/admin/settings/jira):
   1. In Cortex, click your avatar in the lower left corner, then click **Settings**.
   2. Under "Integrations," click **Jira**.
2. Click **Add configuration**.
3. In the upper right corner of the Jira integration modal, click the dropdown labeled `Cloud`. Select `On-prem (basic auth)`.
4. Configure the Jira integration form:
   * **Account alias**: Enter an alias for your account.
   * **Host**: Enter the URL for your Jira on-premises host.
   * **Frontend host**: Enter the URL for your Jira on-premises frontend host.
   * **Username** and **Password**: Enter your Jira username and password.
5. Click **Save**.
   {% endtab %}

{% tab title="On-prem (OAuth)" %}
**Jira on-prem (OAuth)**

**Prerequisites**

To integrate Cortex with Jira using OAuth, you must be running a self-hosted Jira instance with Jira server version 8.22 or higher.

If you're using a self-hosted instance of Jira, you'll need to verify that your Cortex instance is able to reach the Jira instance.\
\
We route our requests through a static IP address. Reach out to support at <help@cortex.io> to receive details about our static IP. If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your Jira instance.

**Step 1: Create an application link from Jira**

1. In your Jira server, navigate to Settings > Applications > Application Links. Click **Create link**.
2. Configure the application link settings:
   * **Application type**: Select `External`.
   * **Direction**: Select `Incoming`.
   * **Redirect URL**: For default configuration, enter the URL of your Cortex instance appended with `/oauth/internal/jira`. For a non-default configuration, enter the URL of your Cortex instance appended with `/oauth/internal/jira/`.
   * **Permission**: Select `write`.
3. Click **Save**.
4. The application link will have an associated client ID and client secret. Copy these values and store them in a secure location, as you will need them in the next steps.

**Step 2: Configure the integration in Cortex**

1. In Cortex, navigate to the [Jira settings page](https://app.getcortexapp.com/admin/settings/jira):
   1. In Cortex, click your avatar in the lower left corner, then click **Settings**.
   2. Under "Integrations," click **Jira**.
2. Click **Add configuration**.
3. In the upper right corner of the Jira integration modal, click the dropdown labeled `Cloud`. Select `On-prem (OAuth)`.
4. Configure the Jira integration form:
   * **Account alias**: Enter an alias for your account.
   * **Host**: Enter the URL for your Jira on-premises host.
   * **Frontend host**: Enter the URL for your Jira on-premises frontend host.
   * **Client ID** and **Client secret**: Enter the client ID and secret associated with the application link you created in the previous steps.
5. Click **Save**.
6. You will be redirected to the Jira settings page. Click **Install** next to your integration name.
   * A confirmation modal will appear, asking you to allow Cortex access to your Jira account.
   * The accessing user can be a user persona or a system account. We recommend using a system account to maintain your organization's access in case the user who set up the integration leaves your organization.
     {% endtab %}

{% tab title="Relay broker" %}
**Configure Jira with Cortex Axon Relay**

See [Internally hosted integrations](/ingesting-data-into-cortex/integrations/axon-relay) for instructions.
{% endtab %}
{% endtabs %}

**Configure the integration for multiple Jira accounts**[**​**](https://docs.cortex.io/docs/reference/integrations/jira#configure-the-integration-for-multiple-propsintegration-accounts)

The Jira integration has multi-account support. You can add a configuration for each additional by repeating the process above.

Each configuration requires an alias, which Cortex uses to correlate the designated with registrations for various entities. Registrations can also use a default configuration without a listed alias. You can edit aliases and default configurations from the Jira page in your Cortex settings. Select the edit icon next to a given configuration and toggle **Set as default** on. If you only have one configuration, it will automatically be set as the default.

## Set a default JQL query for your Jira integration

You can set a custom JQL query for your [Jira integration instances](#tenant-level) and for [individual entities](#entity-level). This allows you to filter which Jira work items are surfaced on entity pages or in other places in Cortex where CQL is used.

The default JQL applies to `jira.issues()` and `jira.numOfIssues()` but not to `jira.rawJql()`.

{% hint style="warning" %}
Note that if you define additional filter logic for your default JQL query when writing a Scorecard rule, you must add that logic in a filter clause. See [Adding filter logic to the default JQL query in a Scorecard](#adding-filter-logic-to-the-default-jql-query-in-a-scorecard) for more information.
{% endhint %}

{% tabs %}
{% tab title="Tenant level" %}
**Set default JQL query at a tenant level**

From the [Jira settings page](https://app.getcortexapp.com/admin/settings/jira) in Cortex, you can set a custom JQL query for your Jira integration.

When Cortex queries for Jira work items, the `statusCategory` is directly grabbed from the [API response](https://docs.atlassian.com/DAC/javadoc/jira/reference/com/atlassian/jira/issue/status/category/StatusCategory.html).

The default query — `statusCategory in ("To Do", "In Progress")` — will filter your Jira tickets to display only those with `To Do` and `In Progress` statuses, excluding closed tickets. The `indeterminate` status category will map to `In Progress` according to the API. Cortex does not use the `status` field for mapping these categories.

Entering a custom JQL query on the Jira integration settings page allows you to override the default for all entities in your workspace. To map work items with a custom status, you can write a custom JQL query that uses `status` instead of `statusCategory`.
{% endtab %}

{% tab title="Entity level" %}
**Set default JQL query at entity level**

You can configure default JQL for entities in their [entity YAML](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file). For example:

```yaml
x-cortex-issues:
    jira:
      projects:
      - name: PROJECT_A
        alias: Jira Project A
      defaultJql: "project = project_a"
```

{% endtab %}
{% endtabs %}

### Fallback logic for default JQL

It is possible to set custom JQL at both the entity and tenant level, but note the fallback logic:

1. If any JQL is passed into a query, Cortex uses that.
2. If not, Cortex uses entity-level default JQL.
3. If not, Cortex uses tenant-wide default JQL.
4. If none, then no JQL is used for filtering.

### Adding filter logic to the default JQL query in a Scorecard

The CQL statement will use the default JQL setting in a Scorecard rule only if you do not define additional filter logic. Any filter logic applied to the statement will override the default JQL query.

To work around this: If you need to include additional filter logic on your query in a Scorecard, you can move the filter logic to the filter clause.

For example, if your default JQL query is set to `"project = project_a"`, then you can add `jira.issues()` to a Scorecard rule to automatically surface only the work items relating to Project A. However, you cannot use `jira.issues(some_other_filter_logic)` in a Scorecard; Cortex will not append your default JQL to the additional filter logic.

In this example, the workaround would be to add a filter clause:\
`jira.issues().filter(some_other_filter_logic)`.

## How to connect Cortex entities to Jira labels, components, or projects

### Discovery

By default, Cortex will tie Jira tickets to entities by searching for any tickets where the `label`, `component`, or `project` field for the work item includes the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag). For example, if your Cortex tag is “my-entity,” then the corresponding tickets in Jira should have “my-entity” as a label, component, or project.

If your Jira label/component/project doesn't cleanly match the Cortex tag, you can override this in the Cortex [entity descriptor](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file).

Without an override, a ticket's label, component, or project must **exactly match** the Cortex tag in the descriptor.

### Connecting via YAML or the Cortex UI

{% tabs %}
{% tab title="Cortex UI" %}
**Connect Jira entities via the Cortex UI**

1. Navigate to an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details) in Cortex.
2. In the upper right corner, click **Configure entity**.\\

   <div align="left"><figure><img src="/files/fEmHBrIb2mtAqwGC1cAq" alt="In the upper right side of an entity, click &#x22;Configure entity.&#x22;"><figcaption></figcaption></figure></div>
3. Click the **Project management** tab, then click **+Add**.\\

   <div align="left"><figure><img src="/files/kk3PZy29TlklC80hsEfh" alt="Click Project management, then click Add." width="563"><figcaption></figcaption></figure></div>
4. In the side panel, configure the details:
   * **Jira service type**: Choose component, label, or project.
   * **Alias**: If you have multiple Jira configurations, select which one this service is associated with.
   * **Name**: Enter the name of the service.
5. At the bottom of the side panel, click **Add**.
   {% endtab %}

{% tab title="Entity YAML" %}
**Editing the entity descriptor**

If you need to override automatic discovery, you can define `x-cortex-issues` blocks in your Cortex entity descriptor.

Note: For all of the following, `alias` is optional, and the default Jira configuration will be used if not provided. You can use Jira `labels`, `components`, or `projects` to match entities.

Each of these blocks has the same field definitions.

| Field   | Description                                                                                      | Required |
| ------- | ------------------------------------------------------------------------------------------------ | :------: |
| `name`  | Label name in Jira                                                                               |   **✓**  |
| `alias` | Alias for the configuration in Cortex (only needed if you have opted into multi-account support) |          |

```yaml
x-cortex-issues:
  jira:
    labels:
      - name: labelA
        alias: alias1
      - name: labelB
```

```yaml
x-cortex-issues:
  jira:
    components:
      - name: component1
        alias: alias1
```

```yaml
x-cortex-issues:
  jira:
    projects:
      - name: project1
        alias: alias1
```

```yaml
x-cortex-issues:
  jira:
    labels:
      - name: label1
      - name: label2
      - name: label3
    components:
      - name: component1
      - name: component2
```

By default, Cortex will surface outstanding issues per entity in the catalog with a default [JQL](https://www.atlassian.com/blog/jira-software/jql-the-most-flexible-way-to-search-jira-14) query: `statusCategory in ("To Do", "In Progress")`. If you'd like to override this, you can provide a new default query with:

```yaml
x-cortex-issues:
  jira:
    defaultJql: 'status = "In Progress"'
```

{% endtab %}
{% endtabs %}

### Identity mappings

Cortex maps Jira accounts to team members defined in the team catalog, so you do not need to define Jira users in a team member's YAML file.

You can confirm that users' Jira accounts are connected from the [Jira user mappings section in Settings](https://app.getcortexapp.com/admin/settings/jira-mappings).

## Using the Jira integration

#### Entity pages

Once the integration is established, you'll be able to pull in data about the work items in any linked Jira instances for a given entity:

* **Number of issues:** Unresolved issues associated with an entity that have the JQL status "in progress" or "to do"
* **Number of issues from JQL query:** Issues associated with an entity that match an arbitrary JQL query

Cortex will tie Jira tickets directly to entities within the catalog. Click **Issue tracking** in the entity's sidebar to see associated Jira tickets.

From this tab you can find a list of all issues with a label that matches the Cortex tag.

* **Key:** The issue key (or "ticket number") for a Jira work item.
* **Issue summary:** Title of the Jira work item and the user designated as the issue reporter.
* **Assignee:** User designated as the work item assignee.
* **Priority:** The work item's priority level in Jira - Lowest, Low, Medium, High, Highest. This will display with the [icon](https://support.atlassian.com/jira-service-management-cloud/docs/what-are-priority-levels-in-jira-service-management/) that corresponds to the priority level in your Jira instance.
* **Created:** Date the work item was created.
* **Due:** Due date for the work item, if applicable.

This list will also be available from a team's homepage when the team's Cortex tag matches a `label`, `component`, or `project` in Jira.

#### Initiatives

Initiatives allow you to set deadlines for specific rules or a set of rules in a given Scorecard and send notifications to users about upcoming due dates.

From the Issues tab of an Initiative, you can automatically create a Jira ticket from a failing rule.

Read about creating Jira issues from Initiatives in the documentation: [Creating issues based on initiatives](/improve/initiatives/issue-config).

#### Dev homepage

The Jira integration enables Cortex to pull information about issues into the [dev homepage](/streamline/homepage). You can find open work items assigned to you under the [Issues tab](https://app.getcortexapp.com/admin/home?activeTab=Issues). The work items that display will depend both on the Jira instances you've connected and the JQL query defined in Settings.

Work items are refreshed every 5 minutes. You can use the **Refresh work items** button to manually refresh issues at any point.

### Scorecards and CQL

With the Jira integration, you can create Scorecard rules and write CQL queries based on Jira work items.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Issues</summary>

Number of **unresolved** issues associated with the entity, where unresolved is defined as the JQL status = "Open" OR status = "To Do".

**Definition:** `jira.numOfIssues()`

**Example**

For a Scorecard measuring entity maturity, you can use this expression to make sure entities have fewer than 3 Jira issues:

```
jira.numOfIssues() <= 10
```

</details>

<details>

<summary>Issues from JQL query</summary>

Number of issues associated with the entity based on arbitrary JQL query.

**Definition:** `jira.numOfIssues(jqlQuery: Text | Null)`

**Example**

For a more specific rule in an entity maturity Scorecard, you can use this expression with a JQL query to make sure entities have no more than 3 open customer-facing tickets.

```
jira.numOfIssues("status = \"Open\" and labels = \"customer-facing\"") <= 3
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

The [engineering homepage](/streamline/homepage) runs a background job every 5 minutes to refresh the Issues tab.

## FAQs and troubleshooting

**I've added a Jira integration, but I'm not sure what JQL is being generated to query Jira.**

When running Scorecard rules, Cortex appends `AND (component = cortex-tag OR labels = cortex-tag OR project = cortex-tag)` to the [JQL you defined](#jira-default-jql), where `cortex-tag` is the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag).

**My Scorecard rules are failing, even though there are tickets in my Jira instance.**

Make sure that the ticket has a label, component, or project that matches **exactly** with the Cortex tag or the list defined in your entity descriptor.

**I received "Configuration error: Integration error for Jira: Unexpected HTTP response 0".**

When using Jira Cloud, you'll need to create a Jira API token and add it on in Jira Settings in Cortex. The email address in Settings **must be the same as the user that the token is associated with**. Cortex also expects only the subdomain of your Jira instance, not the entire URL.

**I received "Configuration error: Jira: Unexpected HTTP response 403: Forbidden".**

1. Make sure that the entity name in Cortex matches the label, component, or project name in Jira.
2. Make sure the subdomain and base URL correspond with the Jira instance you're trying to connect.
3. Verify that the Jira token you added is still valid. You can run the following [curl command](https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/#supply-basic-auth-headers) to confirm:

```
curl -D- \
-X GET \
-H "Authorization: Basic {{your-token}}" \
-H "Content-Type: application/json" \
"https://{{your-domain}}.atlassian.net/rest/api/2/issue/{{valid-ticket-number}}"
```

**I configured the integration, but I am not seeing Work Items populate.**

The background job fetches work items every 5 minutes. However, a fresh integration configuration may result in longer waiting times, as it also fetches historical data.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Kubernetes

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Kubernetes](https://kubernetes.io) is a container orchestration system that automates software deployment, scaling, and management. The Cortex K8s agent is a lightweight agent that collects information from your cluster (Deployments, StatefulSets, Argo Rollouts, and CronJobs) and surfaces it in your Cortex workspace's catalog, Scorecards, and more.

Integrating Kubernetes with Cortex allows you to:

* [Discover and import services](#connecting-cortex-entities-to-kubernetes) directly from K8s clusters into Cortex, making it easy to keep the catalog in sync with what's actually running in production
* [View Kubernetes data on entity pages](#view-kubernetes-data-on-entity-pages) in Cortex, giving you visibility into your infrastructure and how services are deployed
* Create [Scorecards](#scorecards-and-cql) to track progress and drive alignment on projects relating to Kubernetes, and to enforce Kubernetes best practices

## How to configure Kubernetes with Cortex

### Prerequisites

Before getting started:

* [Reach out to the Cortex customer engineering team](#still-need-help) for the Helm chart used for deployment and a username and password.
* [Generate an API key](/configure/settings/api-keys) in Cortex.
  * The API key should have the `User (edit catalog entities)` role at a minimum.
  * Note: It is also possible to programmatically create your API key via the [Cortex API](/api/readme/api-keys).

#### Security considerations

The Cortex k8s agent uses a push model that ensures you do not need to expose your cluster to the public internet.

Additionally, the Helm chart comes with a predefined `ClusterRole` that provides the correct RBACs:

* **Permissions:** `["get", "watch", "list"]`
* **Resources:** `["deployments", "services", "pods", "replicationcontrollers", "statefulsets", "rollouts", "cronjobs"]`
* **API groups:** `["apps", "argoproj.io", "batch"]`

Communication out of the cluster to Cortex happens over HTTPS. There is no inbound traffic to the agent.

### Install the Cortex k8s agent in your Kubernetes cluster

To connect Cortex to your Kubernetes instance, you’ll need to install the Cortex k8s agent in your Kubernetes cluster. The agent is lightweight and adds negligible impact to your cluster.

1. Create a Docker image pull secret:

   ```
   kubectl create secret docker-registry cortex-docker-registry-secret \
   --docker-server=ghcr.io \
   --docker-username={provided by Cortex} \
   --docker-password={token provided to you by the Cortex team} \
   --docker-email={email address}
   ```
2. Run the following command, replacing `cortex-key` with the value of your Cortex API key, to create a secret in your cluster:

   ```
   kubectl create secret generic cortex-key --from-literal api-key=
   ```
3. Run the following command to install the Helm chart provided by Cortex:

   ```
   helm install  ./helm-chart
   ```

## Connecting Cortex entities to Kubernetes

### Discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) as the "best guess" for Kubernetes resource. For example, if your Cortex tag is `my-entity`, then the corresponding resource in Kubernetes should also be `my-entity`.

If your Kubernetes resource don’t cleanly match the Cortex tag, you can override this in the Cortex entity descriptor.

### Methods for mapping Kubernetes resources

See the table below for the methods of mapping resources to entities:

<table><thead><tr><th width="230">Method</th><th width="154.5728759765625">Use case</th><th>Action</th></tr></thead><tbody><tr><td><a href="#annotation">Annotation-based mapping</a></td><td>Services that own their K8s infra</td><td>By default, Cortex maps Kubernetes deployments with a <code>cortex.io/tag</code> annotation to Cortex entities with the same tag.<br><br>Annotation mapping should be at the default absolute path of <code>.metadata.annotations."cortex.io/tag"</code>.</td></tr><tr><td><a href="#label-based">Label-based auto-mapping</a></td><td>Shared infra or external-managed services</td><td>Specify a list of label keys in the Kubernetes integration settings page of your Cortex workspace</td></tr><tr><td><a href="#entity-yaml">Manual link in entity YAML</a></td><td>Complex or legacy workloads</td><td>Add the resource manually to your entity descriptor</td></tr></tbody></table>

See the tabs below to learn how to use each option:

{% tabs %}
{% tab title="Annotation" %}
**Annotation**

You can link your Kubernetes deployment to a Cortex entity by [adding an annotation](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) to your k8s deployment metadata. By default, Cortex maps Kubernetes deployments with a `cortex.io/tag` annotation to Cortex entities with the same tag.

Use `cortex.io/tag` as the key and use the value of `x-cortex-tag` in the Cortex entity's `cortex.yaml` as the value.

For example, if the `cortex.yaml` file is:

```yaml
openapi: 3.0.1
info:
  title: My Service
  x-cortex-tag: my-service
  x-cortex-type: service
  description: This is my cool service.
```

Then the `deployment.yaml` file should be configured as:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-name
  namespace: my-namespace
  annotations:
    cortex.io/tag: my-service
```

**Customize annotation mapping**

It is possible to customize annotation mapping in Cortex:

<details>

<summary>Customize annotation mapping</summary>

1. In Cortex, navigate to the [Kubernetes settings page](https://app.getcortexapp.com/admin/integrations/k8s):
   * Click **Integrations** from the main nav. Search for and select **Kubernetes**.
2. Optionally enter a JQ mapping into the **Annotation mapping** field.
3. Click **Save mapping**.

Note that Cortex looks at the top-level metadata annotations on the Deployment object itself (`metadata.annotations`), not the pod template annotations (`spec.template.metadata.annotations`).

If your automapping is not working as expected, make sure the annotation mapping is at the correct default absolute path of `.metadata.annotations."cortex.io/tag"`, or update the annotation mapping in the K8s configuration page to match the exact absolute path of the Cortex tag.

**Example**

Let's say, for example, your `deployment.yaml` includes `my.service` as the `cortex.io/tag`:

```yaml
metadata:
  name: my-name
  namespace: my-namespace
  annotations:
    cortex.io/tag: my.service
```

If this deployment should be mapped to a Cortex entity with the tag `my-entity`, you can enter the following JQ expression to convert all periods in the deployment annotation tag to dashes:

```
.metadata.annotations."cortex.io/tag" | gsub("\\."; "-")
```

</details>
{% endtab %}

{% tab title="Label-based" %}
**Label-based auto-mapping**

You can override [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) discovery and have Cortex discover Kubernetes resources using their metadata labels instead:

<details>

<summary>Customize label-based auto-mapping</summary>

1. In Cortex, navigate to [**Integrations > Kubernetes**](https://app.getcortexapp.com/admin/integrations/k8s).
2. Under the **K8s auto-mapping customization**, specify a list of metadata label keys.
3. When you are finished, click **Save**.

Once the list is saved, Cortex will discover all Kubernetes resources with metadata labels with the following criteria:

* The resource's spec metadata key contains any of the specified labels
* The key values match a Cortex entity tag

**Example**

For example, let's say you have two Cortex entities (`example` and `entity`), and the following Kubernetes JSON blob:

```
{
  "name": "Sample Kubernetes resource",
  "metadata": {
    "labels": {
      "app": "example",
      "another": "entity"
    }
  }
}
```

By default, `example` and `entity` will have no Kubernetes resource mappings. If the list of metadata labels is set to `["app"]`, then entity `example` will be associated with "Sample Kubernetes resource." If the list is set to `["app", "another"]`, then both `example` and `entity` will be associated with the resource.

</details>
{% endtab %}

{% tab title="Entity YAML" %}
**Editing the entity descriptor**

Cortex accepts several k8s resources, which can be on different clusters or of different types: deployments, ArgoCD rollout, StatefulSet, and CronJob.

All of these resource types have the same field definitions:

| Field        | Description                                                    | Required |
| ------------ | -------------------------------------------------------------- | :------: |
| `identifier` | `namespace/name` as found in Kubernetes                        |   **✓**  |
| `cluster`    | The name of the cluster, which is set when deploying the agent |          |

**Deployments**

```yaml
x-cortex-k8s:
  deployment:
    - identifier: namespace/name
      cluster: dev
    - identifier: experiment/scratch
      cluster: dev
    - identifier: default/cortex
      cluster: prod
```

**ArgoCD Rollout**

```yaml
x-cortex-k8s:
  argorollout:
    - identifier: namespace/name
      cluster: dev
```

**StatefulSet**

```yaml
x-cortex-k8s:
  statefulset:
    - identifier: namespace/name
      cluster: dev
```

**CronJob**

```yaml
x-cortex-k8s:
  cronjob:
    - identifier: namespace/name
      cluster: dev
```

{% endtab %}
{% endtabs %}

### Import entities from Kubernetes

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on manually importing entities.

## Using the Kubernetes integration

### View Kubernetes data on entity pages

Kubernetes deployment data will be available in the **Kubernetes** block on the [entity details pages](/ingesting-data-into-cortex/entities-overview/entities/details) for entities imported from Kubernetes or linked to a k8s resource.

<figure><img src="/files/wjBj9kRNaT2DwZeYidNB" alt="Kubernetes data appears in the Kubernetes block on the entity details page overview."><figcaption></figcaption></figure>

In the entity's sidebar, click **Environments** to see Kubernetes deployments, clusters, active replicas, and pending deployments, as well as:

* **Replicas:** Number of available, ready, and desired replicas.
* **Containers:** Resource containers, including requested memory, memory limit, and CPU data. Also includes the full container definition.

<figure><img src="/files/94VYxUW4N1igIYuaim60" alt=""><figcaption></figcaption></figure>

### Scorecards and CQL

With the Kubernetes integration, you can create Scorecard rules and write CQL queries based on Kubernetes resources. For an example, see Cortex's prebuilt [Kubernetes Deployment Baseline Scorecard](/guides/migrations-and-modernization/accelerate-migration-to-k8s#create-a-kubernetes-scorecard) template.

See more rule examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Cluster information</summary>

Data about k8s clusters associated with a given entity.

**Definition:** `k8s.clusters()`

**Examples**

You can use the `k8s.clusters()` expression in the Query Builder to find all clusters that start with "dev":

```
k8s.clusters.all((cluster) => cluster.name.matches("""dev-.*"""))
```

Or any cluster named "prod":

```
k8s.clusters.any((cluster) => cluster.name.matches("prod"))
```

</details>

<details>

<summary>Deployment labels</summary>

Checks deployment metadata.

**Definition:** `k8s.metadata()`

**Examples**

You can use this expression in a production readiness Scorecard to check ownership:

```
k8s.metadata().labels.any((label) => label.get("ownership") == "ownership_team")
```

This rule checks an entity's metadata labels for the ownership annotation and will pass if "ownership\_team" is defined.

You can also use this expression in the Query Builder to find all k8s deployments with the label "environment":

```
k8s.metadata().labels.all((label) => label.containsKey("environment")) == true
```

Or you could refine the query further to find k8s deployments with an "environment" label and that are in production:

```
k8s.metadata().labels.all((label) => label.get("environment")?.matches("prod")") == true
```

</details>

<details>

<summary>K8s resource is set for entity</summary>

Checks whether a k8s resource of any type is associated with an entity.

**Definition:** `k8s != null`

**Example**

For a Scorecard focused on automation or development maturity, you can set a rule to make sure a k8s resource is mapped:

```
k8s != null
```

</details>

<details>

<summary>Kubernetes spec YAML</summary>

The [Cortex k8s agent](#install-the-cortex-k8s-agent-in-your-kubernetes-cluster) periodically sends the raw spec definitions for all entities. The spec JSON is equivalent to the **root spec field** of the entity descriptor (deployments, StatefulSet, etc.) and fully conforms to that format.

You can find the official documentation for these resource objects in the [Kubernetes Workload Docs](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/).

You can use this list of JSON specs combined with jq or [Open Policy Agent (OPA) language](https://www.openpolicyagent.org/docs/v0.52.0/) to write complex assertions such as "all resources must have specific annotations set" or "all containers should have a CPU resource limit defined."

The list of JSON specs can also be filtered to only ones in a specific cluster by specifying the cluster name: `k8s.spec("prod")`.

**Definition:** `k8s.spec()`

**Examples**

You can use this expression to write a wide range of rules. For a best practices Scorecard, you can make sure that resource definitions have set CPU requests:

```
jq(k8s.spec(), ".[].template.spec.containers[].resources.requests.cpu") != null
```

Or that all resource definitions expose only TCP ports:

```
jq(k8s.spec(), ".[].template.spec.containers[].ports[].protocol") == "TCP"
```

</details>

<details>

<summary>Replica information</summary>

Number of replicas available, current, desired, ready, unavailable, or updated.

**Definition:** `k8s.replicas()`

**Example**

You can use this expression in a development maturity Scorecard to make sure an entity has at least two available instances:

```
k8s.replicas().numAvailable >= 2
```

</details>

## Background sync

The Cortex k8s agent is a cron job that runs every 5 minutes by default.

## FAQs and troubleshooting

#### **When I try to import entities, I don't see all the supported workload types (deployments, ArgoCD rollout, StatefulSet, CronJob)**

Make sure that the types you expected to see are in the cluster you are attempting to import.

#### **Missing namespaces from Kubernetes discovery**

If you're using [Cortex's k8s agent](#cortex-k8s-agent) to import entities into Cortex but don't see all expected namespaces during the import process, make sure `app.namespace` is commented out in `values.yaml`:

```
app:
  # baseURL: 
  baseURL:
  keySecret:
  # namespace: exampleNamespace
```

If `app.namespace` is defined the Cortex k8s agent will only be able to discover services from that namespace. This behavior can be confirmed with a backend log similar to:

```
INFO 1 --- [ scheduling-1] k8sagent : Looking for stateful sets in namespace 
```

Once `app.namespace` is commented out, restart your pods. You will then be able to see all expected namespaces when importing new services.

#### **Helm chart and deprecated Kubernetes Docker registry**

If your Cortex agent in Kubernetes clusters is blocked due to deprecation of Docker registry after an upgrade, you can make these direct edits using the same credentials:

1. **Access the image** from `ghcr.io` instead of `docker.pkg.github.com`.

   ```
   image: ghcr.io/cortexapps/k8s-agent...
   ```
2. **Update the registry secret**, setting the server to `https://ghcr.io`.

If you are unable to make these changes, please reach out to <help@cortex.io> and request a new Helm chart with this change already reflected.

#### **Failing ArgoCD rollouts error in the k8s agent**

When running the self-hosted Kubernetes agent successfully, users may see failing ArgoCD rollouts errors while not using this tool.

```
Error polling argocd rollouts from Kubernetes API

io.kubernets.client.openapi.ApiException:
[...]
  at com.brainera.k8sSDKClient.getArgoRollouts(k8sClient.kt:101) ~[app:/na]
```

Cortex logs this exception for verbosity - this error is harmless if not using ArgoCD tool.

#### **Can I deploy on prem if I don’t use Kubernetes?**

Yes - the Cortex Helm chart deploys two Cortex-specific pods from images for the frontend and backend, as well as a data store. You can use these images to run Docker containers on other platforms, such as ECS.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# LaunchDarkly

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[LaunchDarkly](https://launchdarkly.com/) is a feature flag management platform.

Integrating Cortex with LaunchDarkly allows you to:

* Track LaunchDarkly feature flags on entities in the catalog.
* Create [Scorecards](/standardize/scorecards) that track progress and drive alignment on projects involving your LaunchDarkly feature flags.
* Perform tasks relating to LaunchDarkly feature flags as a part of a [Workflow](/streamline/workflows).
  * For example, you can include a "Create feature flag" step within a Workflow.

## How to configure LaunchDarkly with Cortex

### Prerequisites

Before getting started, create a [LaunchDarkly access token](https://app.launchdarkly.com/settings/authorization) with:

* The `Writer` role
  * If you are not adding LaunchDarkly-related tasks to your [Workflows](/streamline/workflows), you can configure the token with the `Reader` role.
* `20220603` as the API version

### Configure the integration in Cortex

1. In Cortex, navigate to the [LaunchDarkly settings page](https://app.getcortexapp.com/admin/integrations/launchdarkly):
   * Click **Integrations** from the main nav. Search for and select **LaunchDarkly**.
2. Click **Add configuration**.
3. Configure the integration details:
   * **Account alias**: Enter the alias for this configuration.
   * **Access token**: Enter your LaunchDarkly access token.
   * **Environment**: Select your environment.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

#### **Configure the integration for multiple LaunchDarkly accounts**[**​**](https://docs.cortex.io/docs/reference/integrations/github#configure-the-integration-for-multiple-propsintegration-accounts)

The LaunchDarkly integration has multi-account support. You can add a configuration for each additional organization, instance, or account by repeating the process above.

Each configuration requires an alias, which Cortex uses to correlate the designated organization, instance, or account with registrations for various entities. Registrations can also use a default configuration without a listed alias. You can edit aliases and default configurations from the LaunchDarkly page in your Cortex settings. Select the edit icon next to a given configuration and toggle **Set as default** on. If you only have one configuration, it will automatically be set as the default.

## How to connect Cortex entities to LaunchDarkly

### Discovery

By default, Cortex will try to "best-guess" the corresponding project in LaunchDarkly based on the key or tags.

Cortex first looks up a LaunchDarkly project using the entity name (e.g. `My Service`), then the entity identifier (e.g. `my-service`). For example, if your entity name is “My Service”, then the corresponding LaunchDarkly project's key or tag should contain either “My Service” or "my-service".

If no project was matched, Cortex will try to "best-guess" feature flags from all available projects using feature flag tags.

### Editing the entity descriptor

You can find the project key and tags in LaunchDarkly under **Account settings > Projects**. The URL for the project will contain the key. For example: `https://app.launchdarkly.com/projects/default/settings/environments`.

If you prefer to use the project tags in the registration instead, you can find it in the projects table or project settings page.

```yaml
x-cortex-launch-darkly:
  projects:
    - key: project-key
      environments: # Optional
        - environmentName: prod
        - environmentName: staging
      alias: alias-1 # alias is optional and only relevant if you have opted into multi account support
    - tag: project-tag
      environments: # Optional
        - environmentName: prod
      alias: alias-2 # alias is optional and only relevant if you have opted into multi account support
  feature-flags:
    - tag: feature-flag-tag
      environments: # Optional
        - environmentName: staging
      alias: alias-3 # alias is optional and only relevant if you have opted into multi account support
```

## Using the LaunchDarkly integration <a href="#still-need-help" id="still-need-help"></a>

### Scorecards and CQL <a href="#still-need-help" id="still-need-help"></a>

With the LaunchDarkly integration, you can create Scorecard rules and write CQL queries based on LaunchDarkly projects.

See more examples in the [CQL explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if LaunchDarkly project is set</summary>

Check if entity has a registered LaunchDarkly project in its [entity descriptor](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file). If no registration exists, we'll try to automatically detect which corresponding LaunchDarkly project is associated with the entity.

**Definition**: `launchDarkly (==/!=) null`

**Example**

For example, you could write a rule in a Scorecard to check whether an entity has a LaunchDarkly project set:

```
launchDarkly != null
```

</details>

<details>

<summary>Feature flags</summary>

List of flags

**Definition**: `launchDarkly.flags()`

**Example**

In a Scorecard, you could write a rule to check whether an entity has fewer than 10 flags:

```
launchDarkly.flags().length < 10
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## FAQs and troubleshooting

#### **How often does the integration poll for new flags?**

A scheduled job runs every 2 hours to check for new flags.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Lightstep

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

### Overview

[ServiceNow Cloud Observability](https://www.servicenow.com/products/observability.html), formerly known as Lightstep, helps you detect changes in your logs, metrics, and traces. Integrate Lightstep with Cortex to drive insights into SLOs and latency and error rate metrics.

### How to configure Lightstep with Cortex

#### Prerequisite

Before getting started, create a [Lightstep API key](https://docs.lightstep.com/docs/create-and-manage-api-keys).

#### Configure the integration in Cortex

1. In Cortex, navigate to the [Lightstep settings page](https://app.getcortexapp.com/admin/integrations/lightstep):
   * Click **Integrations** from the main nav. Search for and select **Lightstep**.
2. Click **Add configuration**.
3. Configure the Lightstep integration form:
   * **Org ID**: Enter your Lightstep organization ID.
     * You can find this in your Lightstep project settings.
   * **Project ID**: Enter the Lightstep project ID.
     * You can find this in your Lightstep project URL, e.g., `https://app.lightstep.com/PROJECT_ID/project`
   * **API key**: Enter the API key you generated in Lightstep.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

### Linking SLOs in Cortex

You can create and manage SLOs by listing relevant latency SLIs through [Streams](https://docs.lightstep.com/docs/monitor-a-service-level-indicator-with-streams). Cortex will pull data from Lightstep, and track against your specified SLO. For example:

```yaml
x-cortex-slos:
  lightstep:
    - streamId: sc4jmdXT
      targets:
        latency:
          - percentile: 0.5
            target: 2
            slo: 0.9995
```

| Field      | Description                                                                                                                   |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
| streamId   | ID of your Lightstep stream, which can be found in Lightstep, through the URL. `https://app.lightstep.com//stream/my-stream/` |
| percentile | Percentile latency for your given streamId, out of 1                                                                          |
| target     | Latency targets in ms. Latency is currently the only target supported                                                         |
| slo        | SLO percentile, out of 1                                                                                                      |

## Using the Lightstep integration

### Entity pages

When an SLO is defined in an entity's descriptor, you'll see detailed data about SLOs in the **Overview** tab.

On the left side of an entity, click **Monitoring > Lightstep** to view the SLO query, target(s), current value for each SLO, a graph of SLO performance over time, and the period of time the SLO is being calculated for. For example, if the time listed is "7 days ago," then the SLO is looking at the time range starting 7 days ago to now.

### Scorecards and CQL

With the Lightstep integration, you can create Scorecard rules and write CQL queries based on Lightstep SLOs.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>SLOs</summary>

SLOs associated with the entity via ID or tags. You can use this data to check whether an entity has SLOs associated with it, and if those SLOs are passing.

**Definition:** `slos: List<SLO>`

**Example**

In a Scorecard, you can use this expression to make sure an entity is passing its SLOs:

```
slos().all((slo) => slo.passing) == true
```

Use this expression to make sure latency Service Level Indicator (SLI) value is above 99.99%:

```
slos().filter((slo) => slo.name.matchesIn("latency") and slo.sliValue >= 0.9999).length > 0
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Mend

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

## Overview

[Mend](https://www.mend.io/) is an automated application security and remediation platform. Integrate Cortex with Mend to drive insights into potential vulnerabilities in your code and your third-party libraries.

Cortex supports integrating with:

* [Mend Static Application Security Testing (SAST)](https://www.mend.io/sast-lp): This product scans for vulnerabilities in the code you write.
* [Mend Software Composition Analysis (SCA)](https://www.mend.io/sca/): This product scans for vulnerabilities in your third-party libraries.

## How to configure Mend with Cortex

See the tabs below for instructions on configuring Mend SAST and Mend SCA.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

{% tabs %}
{% tab title="Mend SAST" %}
**Prerequisite**

Before getting started, [create an API token in Mend](https://docs.mend.io/legacy-sast/latest/api-token).

If you're using a self-hosted instance of Mend, you'll need to verify that your Cortex instance is able to reach the Mend instance.\
\
We route our requests through a static IP address. Reach out to support at <help@cortex.io> to receive details about our static IP. If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your Mend instance.

**Configure the integration in Cortex**

1. In Cortex, navigate to the [Mend settings page](https://app.getcortexapp.com/admin/integrations/mend):
   * Click **Integrations** from the main nav. Search for and select **Mend**.
2. Click **Add configuration**.
3. Configure the Mend SAST integration form:
   * **API token**: Enter the API token you created in Mend.
4. Click **Save**.
   {% endtab %}

{% tab title="Mend SCA" %}
**Prerequisite**

Before getting started, create an [Organization API key](https://docs.mend.io/legacy-sca/latest/global-organization-product-project-api) and a [user key](https://docs.mend.io/legacy-sca/latest/user-level-access-control-in-integrations-and-apis) in Mend.

If you're using a self-hosted instance of Mend, you'll need to verify that your Cortex instance is able to reach the Mend instance.\
\
We route our requests through a static IP address. Reach out to support at <help@cortex.io> to receive details about our static IP. If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your Mend instance.

**Configure the integration in Cortex**

1. In Cortex, navigate to the [Mend settings page](https://app.getcortexapp.com/admin/settings/mend):
   1. In Cortex, click your avatar in the lower left corner, then click **Settings**.
   2. Under "Integrations", click **Mend**.
2. Click **Add configuration**.
3. Configure the Mend SCA integration form:
   * **Organization type**: Select `Global` or `Single`.
   * **Organization API token**: Enter your Global organization key or a single organization key.
     * This can be found in Mend SCA under the [Integrate tab](https://saas.mend.io/Wss/WSS.html#!adminOrganization_integration).
   * **User key**: Enter your Mend user key.
     * This can be found in Mend under **User profile > User keys**.
   * **URL type**: Select your Mend URL type depending on the server URL for your Mend instance.
     * Select **NEW** if the server URL is `saas.mend.io`.
     * Select **LEGACY** if the server URL is `saas.whitesourcesoftware.com`.
     * Select **CUSTOM** if using a dedicated instance.
   * **Custom URL**: If using a dedicated instance, enter your Mend server URL.
4. Click **Save**.
   {% endtab %}
   {% endtabs %}

### Advanced configuration

If you’re unable to expose your Mend instance to be reachable by Cortex, you can set up a Custom Integration Webhook.

## How to connect Cortex entities to Mend

#### Discovery

By default, Cortex will use your associated Git repository (e.g. `repo-name`) as the "best guess" for the Mend SAST application name and the Mend SCA project name.

If your repository names don’t cleanly match the Mend SAST application names or Mend SCA project names, you can override this in the Cortex Service Descriptor.

#### Editing the entity descriptor

```yaml
x-cortex-static-analysis:
  mend:
    applicationIds:
      - mend_id_1
      - mend_id_2
    projectIds:
      - project_id_1
      - project_id_2
```

The application IDs can be found in the Mend SAST web interface.

A project ID can be found in the Mend SCA web interface; while viewing the project, the ID appears in the URL after `project;id=`.

## Using the Mend integration

### Entity pages

From the **Overview** tab on an entity page, you can find vulnerabilities in the **Code and Security** block.

In the left sidebar of an entity, click **Code & security > Mend** to view the total number of vulnerabilities, a risk score, and a list of vulnerabilities including the risk rating and creation date.

### Scorecards and CQL

With the Mend integration, you can create Scorecard rules and write CQL queries based on Mend projects and applications.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Mend project is set</summary>

Check if entity has a registered Mend project

**Definition:** `mend (==/!= null): Boolean`

**Examples**

In a Scorecard, you can write a rule to make sure an entity has a Mend project set:

```
mend != null
```

</details>

<details>

<summary>Vulnerabilities</summary>

List of vulnerabilities, filterable on risk and source

**Definition:** `mend.vulnerabilities(): List`

**Examples**

In a Scorecard, you can write a rule to make sure an entity has fewer than 10 vulnerabilities from both SAST and SCA sources:

```
mend.vulnerabilities(source = ["SAST", "SCA"]).length < 10
```

You can write a rule to make sure an entity has fewer than 3 vulnerabilities with a risk level of "Medium" or "High":

```
mend.vulnerabilities(risk = ["Medium", "High"]).length <= 3
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Microsoft Teams

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Microsoft Teams](https://www.microsoft.com/en-us/microsoft-teams/group-chat-software) is a communication and collaboration platform designed to promote greater productivity through messaging and file-sharing tools.

Integrating Microsoft Teams with Cortex allows you to:

* Quickly find the relevant MS Teams channel to communicate with the right team, allowing for easier collaboration on projects and faster communication during an incident
  * MS Teams channels appear in the "Owners" block on [entity details pages](/ingesting-data-into-cortex/entities-overview/entities/details).
* Receive actionable [notifications](#managing-microsoft-teams-notifications) directly in MS Teams for Scorecard changes, upcoming Initiatives, weekly summaries of entity performance, and more
* Create [Scorecards](/standardize/scorecards) that enforce standards such as having an MS Teams channel set for projects

## How to configure Microsoft Teams with Cortex

{% hint style="warning" %}
This page describes how to integrate Microsoft Teams with Cortex cloud. If you're using a self-managed Cortex instance, you'll need to follow a manual configuration process to use Cortex's app for Microsoft Teams. Follow the [self-managed Teams guide here](/self-managed/features/integrations/ms-teams).
{% endhint %}

### Step 1: Configure the integration in Cortex

1. In Cortex, navigate to the [Microsoft Teams settings page](https://app.getcortexapp.com/admin/integrations/microsoftteams).
   1. Click **Integrations** from the main nav. Search for and select **Microsoft Teams**.
2. Click **Add configuration**.
3. In the side panel, click **Connect account via Microsoft Teams OAuth**. A popup window will appear.
4. In the pop-up window, follow the prompts to log in to your Microsoft account. The user configuring the integration must accept the Application-type permissions listed below:

| Permission                                                                                                        | Requirements                                                                                        | Description                                                                     |
| ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [Get organizations](https://learn.microsoft.com/en-us/graph/api/organization-get?view=graph-rest-1.0\&tabs=http)  | `Organization.Read.All` `Directory.Read.All` `Organization.ReadWrite.All` `Directory.ReadWrite.All` | Enables Cortex to get all organizations and fetch all repos for the import page |
| [Get users](https://learn.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0\&tabs=http)                 | `User.Read.All` `User.ReadWrite.All` `Directory.Read.All` `Directory.ReadWrite.All`                 | Pulls Teams users into Cortex                                                   |
| [Get channels](https://learn.microsoft.com/en-us/graph/api/channel-list?view=graph-rest-1.0\&tabs=http)           | `ChannelSettings.Read.Group`                                                                        | Enables notifications                                                           |
| [Get teams](https://learn.microsoft.com/en-us/graph/api/teams-list?view=graph-rest-1.0\&tabs=http)                | `Team.ReadBasic.All`                                                                                | Enables notifications to teams                                                  |
| [Get team members](https://learn.microsoft.com/en-us/graph/api/team-list-members?view=graph-rest-1.0\&tabs=http)  | `TeamMember.Read.Group`                                                                             | Enables Scorecard rule for Teams                                                |
| [Send messages](https://learn.microsoft.com/en-us/graph/api/channel-post-messages?view=graph-rest-1.0\&tabs=http) | `Teamwork.Migrate.All`                                                                              | Enables notifications for users/team channels                                   |

After authenticating, you will be redirected to the Microsoft Teams integration settings page in Cortex. In the upper right corner of the page, click **Test configuration** to ensure Microsoft Teams was configured properly.

### Step 2: Install the Cortex app for Teams through Microsoft AppSource

1. On the [Microsoft Teams settings page](https://app.getcortexapp.com/admin/settings/microsoftteams) in Cortex, click the [Microsoft AppSource](https://appsource.microsoft.com/en-us/product/teams-app/WA200005959) link.
2. In AppSource, click **Get it now**. You will be redirected to a page where you can choose whether to download a desktop app or use the web app.

### Step 3: Configure a setup policy for Cortex in Teams

MS Teams admins can configure a setup policy for Cortex, can choose whether to automatically download the Cortex app into the personal Teams environments for users, and can choose to pin the app to make it more easily accessible.

If admins do not add a policy to install the Cortex app, then users will need to download the app during setup.

1. Navigate to the Teams [admin center](https://admin.teams.microsoft.com/) under **Teams app > Setup policies**.
2. Click **Add** to start configuring a setup policy for the Cortex app.
3. After configuring a policy, navigate to the **Installed apps** section. Add the Cortex app here.
   * This will automatically download the app in users' personal Teams environments.
   * MS Teams admins can also apply the policy to specific users in the Teams admin center under **Users > Manage Users**.
4. To pin the app, follow [Microsoft's instructions on pinning apps](https://learn.microsoft.com/en-us/microsoftteams/teams-app-setup-policies#pin-apps).

### Limitations

Cortex does not automatically discover MS Teams channels based on a [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) so you must [define channels for each entity](#editing-the-entity-descriptor) as described below.

## How to connect Cortex entities to Microsoft Teams

In order to use this integration's functionality, your MS Teams channels need to be associated with entities in Cortex. Cortex does not automatically discover channels for MS Teams, so you must define them in the [entity descriptor](#editing-the-entity-descriptor).

### Editing the entity descriptor

To associate a Microsoft Teams channel with an entity, define a `x-cortex-microsoft-teams` block in an [entity descriptor](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file) as shown in the example below.

Defining a Teams channel will provide [direct access to the channel via the entity page](#viewing-microsoft-teams-information-across-cortex) in Cortex.

```yaml
x-cortex-microsoft-teams:
    channels:
    - name: team-engineering
      teamName: engineering
      description: This is a description for the engineering channel in Teams.
      notificationsEnabled: true
```

| Field                  | Description                                    | Required |
| ---------------------- | ---------------------------------------------- | :------: |
| `name`                 | Microsoft Teams channel name **(exact match)** |   **✓**  |
| `teamName`             | Team name **(exact match)**                    |   **✓**  |
| `description`          | Description for the Teams channel              |          |
| `notificationsEnabled` | Boolean to enable/disable notifications        |          |

## Using the Microsoft Teams integration

### Viewing Microsoft Teams information across Cortex

* [Entity details page](/ingesting-data-into-cortex/entities-overview/entities/details): After MS Teams channels are defined in an entity's YAML, MS Teams channels will appear at the top of an entity's overview page in the **MST channels** block. Channels are also listed in the "Owners" page in an entity's sidebar. You can click any channel name to go directly to that channel in Microsoft Teams.\\

  <figure><img src="/files/lCD6qMSOOtSyhbOQoiCz" alt="The MS Teams channels appear in the upper right side of an entity details page."><figcaption></figcaption></figure>
* You can write CQL queries and Scorecard rules based on Microsoft Teams channels. Learn more under [Scorecards and CQL](#scorecards-and-cql).

### Managing Microsoft Teams notifications

After configuring the Microsoft Teams integration, you can choose whether to allow Microsoft Teams notifications for your workspace.

<div align="left"><figure><img src="/files/eAMit5OC0eMiWaWD2jOW" alt="A notification in MS Teams includes actionable information." width="563"><figcaption></figcaption></figure></div>

In Cortex under **Settings > Notifications**, an admin or a user with the `Configure workspace notification settings` permission can enable or disable the option to receive notifications via MS Teams for each type of notification. Users can also adjust their [personal notification settings](/configure/settings/notifications#adjusting-your-personal-notification-subscriptions) to control which notifications they receive via MS Teams.

#### Team, user, and entity MS Teams notifications

Notifications are [user-based, team-based, or entity-based](/configure/settings/notifications#enable-notifications-for-users-teams-and-entities). DMs and channel notifications are sent from the Cortex app.

* User-based notifications are sent to users via a DM from the Cortex app.
* Team-based notifications are sent to the MS Teams channel associated with a team.
* Entity-based notifications are sent to the MS Teams channel associated with an entity.

Learn more about notifications in the [Notifications docs](/configure/settings/notifications).

### Scorecards and CQL

With the Microsoft Teams integration, you can create Scorecard rules and write CQL queries based on Microsoft Teams channels.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Microsoft Teams channel is set</summary>

Checks if a given entity has a registered Teams channel in its entity descriptor.

**Definition:** `microsoftTeams (==/!=) null`

Example

For a Scorecard focused on team operations, you can make sure that each team entity has registered a Microsoft Teams channel:

```
microsoftTeams != null
```

</details>

<details>

<summary>Number of Microsoft Teams channels</summary>

Counts the number of Microsoft Teams channels for a given entity.

* Channel name
* Team name

**Definition**: `microsoftTeams.channels().length`

Example

You can use this expression in the Query builder to identify teams missing a Microsoft Teams channel:

```
microsoftTeams.channels().length < 1
```

</details>

<details>

<summary>Total number of members across Microsoft Teams channels registered for the entity</summary>

Counts the total number of members across all Microsoft Teams channels registered for a given entity.

* Channel name
* Member name
* Team name

**Definition:** `microsoftTeams.members().length`

Example

For a Scorecard focused on team operations, you can verify that the Microsoft Teams channel has at least one member in it:

```
microsoftTeams.members().length > 0
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Privacy Policy

We will retain basic Microsoft Teams metadata like user IDs for the period necessary to fulfill the purposes outlined in our [Privacy Policy](https://www.cortex.io/legal/privacy-policy) unless a longer retention period is required or permitted by law, or where the Customer Agreement requires or permits specific retention or deletion periods.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# New Relic

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[New Relic](https://newrelic.com/) is a performance tracking and analytics tool that helps engineers gain visibility into their software. Integrating New Relic with Cortex allows you to:

* Discover entities and track ownership
* View SLO and monitoring information on entity pages in Cortex
* Embed New Relic dashboards on entity pages in Cortex
* Create Scorecards to drive alignment on projects involving New Relic metrics

## How to configure New Relic with Cortex

### Prerequisite

Before getting started:

* As a full platform user in New Relic, create a [New Relic user key](https://docs.newrelic.com/docs/apis/intro-apis/new-relic-api-keys/#user-key).
  * New Relic user keys are linked to the account they were created from, so if this account is ever deleted, the integration with Cortex will stop working.

### Configure the integration in Cortex

1. In Cortex, navigate to the [New Relic settings page](https://app.getcortexapp.com/admin/integrations/newrelic):
   1. Click **Integrations** from the main nav. Search for and select **New Relic**.
2. Click **Add configuration**.
3. Configure the New Relic integration form:
   * **Account alias:** Enter a name for this account.
   * **Personal key:** Enter the user key you generated in New Relic.
   * **Account ID:** Enter the [ID for the account](https://docs.newrelic.com/docs/accounts/accounts-billing/account-structure/account-id/) that the user key was generated with.
   * **Use EU region:** Optionally enable this toggle to use the EU region of New Relic.
4. Click **Save**.

Once you save your configuration, you'll see it listed on the integration's settings page in Cortex. If you’ve set everything up correctly, you’ll see the option to **Remove Integration** in Settings.

You can also use the **Test all configurations** button to confirm that the configuration was successful. If your configuration is valid, you’ll see a banner that says “Configuration is valid. If you see issues, please see documentation or reach out to Cortex support.”

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

#### Cross-account access

After setting up the integration, you will be redirected to the [New Relic settings page](https://app.getcortexapp.com/admin/settings/newrelic) where you can enable the cross-account access feature. If you have an account that supports subordinate accounts, you can enable this setting to fetch applications and SLOs for all the accounts that are under the configured one.

### **Configure the integration for multiple New Relic accounts**[**​**](https://docs.cortex.io/docs/reference/integrations/newrelic#configure-the-integration-for-multiple-propsintegration-accounts)

The New Relic integration has multi-account support. You can add a configuration for each additional by repeating the process above.

Each configuration requires an alias, which Cortex uses to correlate the designated with registrations for various entities. Registrations can also use a default configuration without a listed alias. You can edit aliases and default configurations from the New Relic page in your Cortex settings. Select the edit icon next to a given configuration and toggle **Set as default** on. If you only have one configuration, it will automatically be set as the default.

## How to connect Cortex entities to New Relic

#### Auto discovery

There are two ways to auto-map New Relic applications and services to Cortex entities:

* By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) or its name as the "best guess" for New Relic applications. For example, if your Cortex tag is `my-entity`, then the corresponding application in New Relic should also be `my-entity`. The name is not case-sensitive.
  * If your New Relic applications don’t cleanly match the Cortex tag or name, you can override this in the Cortex entity descriptor.
* Cortex also supports mapping New Relic applications to Cortex entities via New Relic tagKeys. By default, a Cortex entity will be mapped to a New Relic application or service with New Relic tag key = "service" and tag value = the service's Cortex tag.
  * You can customize the tag key names on the [New Relic settings page](https://app.getcortexapp.com/admin/settings/newrelic) in Cortex.

**Note:** Cortex does not support auto-mapping of SLOs. SLOs have to be defined via the entity YAML or attached to a mapped application or service.

**Dependencies**

Cortex automatically maps dependencies between your entities by utilizing New Relic's [Service Map](https://docs.newrelic.com/docs/new-relic-solutions/new-relic-one/ui-data/service-maps/service-maps/) data.

Say you have two applications in NewRelic (Application A and Application B), and in the service map Application A calls Application B. In Cortex you have two Entities (Cortex Entity A and Cortex Entity B), where Cortex Entity A is mapped to New Relic Application A and Cortex Entity B is mapped to New Relic Application B. Cortex will take the mapped relationship from Application A to Application B and create a dependency from Cortex Entity A to Cortex Entity B.

### Import entities from New Relic

See the [Create services documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services) for instructions on importing entities.

### Editing the entity descriptor

**APM services**

New Relic application metrics can be fetched for each entity using application IDs or tags.

```yaml
x-cortex-apm:
  newrelic:
    applications:
    - applicationId: 1234567
      alias: Default-App
    - applicationId: 8904321
      alias: Another-App
```

While the `applications` wrapper format is the recommended format, Cortex also supports a flat array:

```yaml
x-cortex-apm:
  newrelic:
    - applicationId: 1234567
```

| Field           | Description                                                                                      | Required |
| --------------- | ------------------------------------------------------------------------------------------------ | :------: |
| `applications`  | Specifies that the APM service should be found by application ID                                 |   **✓**  |
| `applicationID` | ID for the application that the service belongs to                                               |   **✓**  |
| `alias`         | Alias for the configuration in Cortex (only needed if you have opted into multi-account support) |          |

```yaml
x-cortex-apm:
  newrelic:
    tags:
    - tag: tagKey
      value: tagValue
      alias: Default-App
```

| Field   | Description                                                                                      | Required |
| ------- | ------------------------------------------------------------------------------------------------ | :------: |
| `tags`  | Specifies that the APM service should be found by tag                                            |   **✓**  |
| `tag`   | Tag key for the APM service(s)                                                                   |   **✓**  |
| `value` | Tag value for the APM service(s)                                                                 |   **✓**  |
| `alias` | Alias for the configuration in Cortex (only needed if you have opted into multi-account support) |          |

Instructions to find your Application ID can be found in the [New Relic docs](https://docs.newrelic.com/docs/apis/rest-api-v2/get-started/get-app-other-ids-new-relic-one). You can also find the Application ID in the URL in New Relic.

You can also find information on finding and managing tags in the [New Relic docs](https://docs.newrelic.com/docs/new-relic-solutions/new-relic-one/core-concepts/use-tags-help-organize-find-your-data/#filter-tags).

**OpenTelemetry**

[OpenTelemetry](https://opentelemetry.io/) services can be associated with the entity only using tags. For this type of service New Relic doesn't generate application ID.

```yaml
x-cortex-apm:
  newrelic:
    tags:
    - tag: tagKey
      value: tagValue
      alias: Default-App
```

| Field   | Description                                                                                      | Required |
| ------- | ------------------------------------------------------------------------------------------------ | :------: |
| `tags`  | Specifies that the OpenTelemetry service should be found by tag                                  |   **✓**  |
| `tag`   | Tag key for the APM service(s)                                                                   |   **✓**  |
| `value` | Tag value for the APM service(s)                                                                 |   **✓**  |
| `alias` | Alias for the configuration in Cortex (only needed if you have opted into multi-account support) |          |

Cortex fetches OpenTelemetry data every 5 minutes, but the data refresh may take longer depending on how much data you have.

**Embeds**

Cortex can also embed dashboards from New Relic.

```yaml
x-cortex-dashboards:
  embeds:
    - type: newrelic
      url: https://chart-embed.service.newrelic.com/example/1a234bc5-d6e7-890f-g123-456h7ij8901 
```

| Field  | Description                                                                                                                                              | Required |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | :------: |
| `type` | Specifies the source of the embed; in this case, should be `newrelic`                                                                                    |   **✓**  |
| `url`  | URL for the dashboard. It must be publicly accessible, or if you can access the iFrame via VPN, it should be accessible in Cortex while also on the VPN. |   **✓**  |

Learn more about embedding charts in the [Adding external docs](/ingesting-data-into-cortex/entities-overview/entities/external-docs) page.

**SLOs**

SLO can be fetched for each entity using New Relic entity GUID for respective SLO or associated service. Detailed instructions how to obtain entity GUID can be found in [New Relic docs](https://docs.newrelic.com/docs/new-relic-solutions/new-relic-one/core-concepts/what-entity-new-relic/#find).

Fetched SLO information can be found in the `Operations` and `Integrations` sections of an entity page.

```yaml
x-cortex-slos:
  newrelic:
    - id: MjU5ODYxOXxFWFR8U0VSVklDRV9MRVZFTHiw0TI5ODQ
      alias: my-default-alias
    - id: MjU5ODYxOXxFWFR8U0VSVklDRV9MRVZFTHiw0TI76QB
      alias: my-other-alias
    - id: MjU5ODYxOXxFWFRAB6VSVklDRV9MRVZFTHiw0TI76QD
```

| Field   | Description                                                                                                                                                     | Required |
| ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------: |
| `id`    | New Relic entity guid for the SLO or the associated service; if you use the GUID for a parent service, all SLOs associated with it will be imported into Cortex |   true   |
| `alias` | Alias for the configuration in Cortex (only needed if you have opted into multi-account support)                                                                |          |

If the alias is not specified, like with the third ID above, Cortex will use the default configuration.

If you use the GUID for a parent service to define the SLOs for a given entity, Cortex will import all SLOs associated with that service.

## Using the New Relic integration

### View New Relic data on entity pages

When entities are tied to New Relic, SLO and monitoring information appear under the Monitoring section on the overview of the [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details).

More data is available under the **Monitoring** page in the entity's sidebar:

* Throughput
* Response time
* Error rate
* Apdex target
* Apdex score
* Host count
* Instance count
* Concurrent instance count

In the SLOs section, you'll be able to see a list of all SLOs tied to that entity, the target and current SLO score, and the period of time the SLO is being calculated for. For example, if the time listed is "7 days ago," then the SLO is looking at the time range starting 7 days ago to now\..

The SLO name will display in green when passing and orange when failing.

If you've defined [dashboards](/ingesting-data-into-cortex/entities-overview/entities/external-docs#embedded-dashboards) in an entity's YAML, you'll be able to view the graphs from an entity's details page. Open the **Dashboard** page in the entity's sidebar. All dashboards defined in the descriptor will be embedded on this page.

New Relic dashboards must be defined individually for each entity.

### Relationship graphs

[Dependencies](#dependencies) detected from New Relic will appear in [Relationship graphs](/ingesting-data-into-cortex/entities-overview/entities/relationship-graph). You can [manually sync dependencies](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/dependencies#sync-dependencies) in the Relationship Graph.

### Scorecards and CQL

With the New Relic integration, you can create Scorecard rules and write CQL queries based on New Relic performance metrics.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Application summary</summary>

Fetch high-level [summary data](https://docs.newrelic.com/docs/apis/rest-api-v2/application-examples-v2/summary-data-examples-v2) for a given New Relic application.

This expression enables you to score entities on reliability metrics:

* Apdex score
* Apdex target
* Concurrent stance count
* Error rate
* GUID
* Host count
* ID
* Instance count
* Name
* Response time
* Throughput
* Type

**If there is not an application ID set in the entity descriptor, a Scorecard rule based on this expression will fail.**

**Definition:** `newrelic.applications()`

**Example**

You can use this expression in a Scorecard rule to make sure entities' Apdex score is at least 0.9:

```
newrelic.applications().all(application) => application.apdexScore >= 0.9
```

</details>

<details>

<summary>New Relic application is set</summary>

Check if entity has a New Relic application ID set in its entity descriptor.

This can be a good companion to other rules that will fail without a defined application ID, like `newrelic.applications()`.

**Definition:** `newrelic (==/!=) null`

**Example**

You can use this expression in an onboarding Scorecard to make sure that entities have a New Relic application ID set:

```
newrelic != null
```

</details>

<details>

<summary>Raw NRQL query</summary>

Execute an arbitrary NRQL query and capture the [raw JSON back out](https://api.newrelic.com/docs/).

This expression is not inherently tied to a single entity and requires a custom query to pull the specific data what you need. The raw JSON can be parsed using JQ or [Open Policy Agent](https://www.openpolicyagent.org/docs/v0.52.0/) language.

**Definition:** `newrelic.rawNrql(query: Text)`

**Examples**

You can use this expression in a Scorecard measuring performance to make sure that the 95th percentile of latency has been less than 500ms in the last 3 weeks for a given entity:

```
jq(newrelic.rawNrql("SELECT percentile(duration) FROM PageView WHERE = '" + newrelic.applications().firstOrNull().name + "' SINCE 3 weeks ago COMPARE WITH 1 week AGO TIMESERIES AUTO"), "[.[].\"percentile.duration\".\"95\"] | add / length") < 500
```

Or you can use this expression in a CQL report to read the timeseries of the `process.cpu.usage` metric for the last 30 minutes using NRQL and a New Relic service GUID:

```
newrelic.rawNrql("SELECT latest(`process.cpu.usage`) FROM Metric WHERE `entity.guid` = '"+newrelic.applications().getOrNull(0)?.guid+"' SINCE 30 MINUTES AGO TIMESERIES")
```

</details>

<details>

<summary>SLOs</summary>

SLOs associated with the entity via ID or tags. You can use this data to check whether an entity has SLOs associated with it and if those SLOs are passing.

SLOs

* History
* ID
* Name
* Operation
* Remaining budget
* SLI value
* SLO target
* Source
* Thresholds

SLO datum (timeseries data for the SLI)

* Datum
* Ts

Named threshold (SLOs thresholds like "warning" or "error" states)

* Name
* Threshold

**Definition:** `slos`

**Examples**

You can use SLO data from New Relic to evaluate entities in Scorecards. For an onboarding Scorecard, you can make sure that entities have at least 1 SLO defined:

```
slos().length > 0
```

For a project standards Scorecard, you can also use this expression to make sure entities are passing all of their SLOs:

```
slos().all((slo) => slo.passing) == true
```

</details>

**OpenTelemetry metrics**

OpenTelemetry metrics available in the [New Relic Metrics Exlorer](https://docs.newrelic.com/docs/query-your-data/explore-query-data/browse-data/introduction-data-explorer/) can be accessed or manipulated for a given entity by combining CQL and [NRQL](https://docs.newrelic.com/docs/nrql/nrql-syntax-clauses-functions/) native query.

<details>

<summary>Accessing OpenTelemetry data with CQL and NRQL</summary>

In Cortex, you can access OpenTelemetry data by incorporating a raw NRQL query into this CQL expression with the associated [New Relic GUID](https://docs.newrelic.com/docs/new-relic-solutions/new-relic-one/core-concepts/what-entity-new-relic/#find).

**Definition:** `newrelic.applications().getOrNull(0)?.guid`

**Example**

You can execute raw NRQL query to collect average `http.server.requests` in a CQL report:

```
newrelic.rawNrql("SELECT average(`http.server.requests`) FROM Metric WHERE `entity.guid` = '"+newrelic.applications().getOrNull(0)?.guid+"' SINCE 7 DAYS AGO")
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Okta

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

## Overview

[Okta](https://www.okta.com/) is an identity and access management (IAM) platform. Integrate Cortex with Okta to drive insights into authentication and ownership.

After configuring the integration, you can set Okta teams and team members as owners of entities.

For information on configuring Okta SSO or Okta SCIM for logging in to Cortex, see the [Okta SSO documentation](/configure/settings/managing-users/configuring-sso) and [Okta SCIM documentation](https://github.com/cortexapps/hippocampus/blob/master/configure/settings/managing-users/configuring-sso/okta/okta-scim.md).

## How to configure Okta with Cortex

### Prerequisites

Before getting started:

* An Okta administrator, with at least the [View groups](https://help.okta.com/en-us/Content/Topics/Security/custom-admin-role/about-role-permissions.htm) permissions, must [create an Okta API token](https://developer.okta.com/docs/guides/create-an-api-token/create-the-token/).
  * Grant the following scopes for the API token:
    * `okta.groups.read`
    * `okta.profileMappings.read`
    * `okta.users.read`
* Obtain your Okta domain.
  * This can be found in the prefix of your Okta URL. For example, `https://domain.okta.com`.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Okta settings page](https://app.getcortexapp.com/admin/integrations/okta):
   * Click **Integrations** from the main nav. Search for and select **Okta**.
2. Click **Add configuration**.
3. Configure the Okta integration form:
   * **Domain**: Enter your Okta domain.
   * **API token**: Enter your Okta API token.
   * **Group types**: Specify which group types to include.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Okta

### Import teams from Okta

See the [Create teams documentation](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams#creating-a-team) for instructions on importing entities.

Team data syncs from Okta daily at 3 p.m. UTC.

### Editing the entity descriptor

```yaml
x-cortex-owners:
  - type: group
    name: Engineering # group name in Okta
    provider: OKTA
    description: This is a description for this owner # optional
```

The group name is case-sensitive and should be exactly the same as in Okta.

## Using the Okta integration

### Scorecards and CQL

With the Okta integration, you can create Scorecard rules and write CQL queries based on Okta teams.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>All ownership details</summary>

A special built-in type that supports a null check or a count check, used to enforce ownership of entities.

**Definition:** `ownership: Ownership | Null`

**Example**

An initial level in a security Scorecard might include a rule to ensure an entity has at least one team as an owner:

```
ownership.teams().length > 0
```

</details>

<details>

<summary>All owner details</summary>

List of owners, including team members and individual users, for each entity

**Definition:** `ownership.allOwners()`

**Example**

The Scorecard might include a rule to ensure that entity owners all have an email set:

```
ownership.allOwners().all((member) => member.email != null)
```

</details>

<details>

<summary>Team details</summary>

List of teams for each entity

**Definition:** `ownership.teams(): List<Team>`

**Example**

The Scorecard might include a rule to ensure that an entity owners all have a description and are not archived:

```
ownership.teams().all(team => team.description != null and team.isArchived == false)
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex conducts an ownership sync for Okta teams every day at 3 p.m. UTC.

## Troubleshooting and FAQ

**I've added an API token but the login is still using Google.**

To set up Okta for SSO, use the [Okta SSO guide](/configure/settings/managing-users/configuring-sso/okta).

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Opsgenie

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

{% hint style="danger" %}
Atlassian is deprecating the Opsgenie product and encouraging their customers to migrate to Jira Service Management. Read more about moving from Opsgenie to Jira Service Management on [Atlassian's web site](https://support.atlassian.com/jira-service-management-cloud/docs/start-shifting-from-opsgenie-to-jira-service-management/).

Cortex is actively working on developing an integration with Jira Service Management.
{% endhint %}

[Opsgenie](https://www.atlassian.com/software/opsgenie) is an alert and on-call management platform from Atlassian.

Integrating Opsgenie with Cortex allows you to:

* Pull in on-call rotation data and escalation policies
  * The on-call user or team will appear in the **Current On-call** block on an entity's details page.
  * You can also view on-call information on an entity page in its side panel under **Integrations > On-call**.
* View alerts from Opsgenie in an entity's event timeline
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your on-call schedules and alerts

## How to configure Opsgenie with Cortex

### Prerequisite

Before getting started, create an [Opsgenie API key](https://support.atlassian.com/opsgenie/docs/api-key-management/) with the following permissions:

* `Read`
* `Configuration Access`

### Configure the integration in Cortex

1. In Cortex, navigate to the [Opsgenie settings page](https://app.getcortexapp.com/admin/integrations/opsgenie):
   * Click **Integrations** from the main nav. Search for and select **Opsgenie**.
2. Configure the Opsgenie integration form:
   * **Subdomain**: Enter the subdomain assigned to your Opsgenie instance.
   * **API key**: Enter your Opsgenie API key.
   * **Use European service region**: Optionally, toggle this setting on to enable the EU region of Opsgenie.
3. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Opsgenie

### Discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) as the "best guess" value for the `backend` and `service` tags on your alerts. For example, if your alert in Opsgenie has the tag `backend:my-entity`, the alert will be automatically associated with the entity in Cortex with a unique identifier of `my-entity`.

If your Opsgenie tags don’t cleanly match the Cortex tag, or you use different identifying tags, you can override this in the Cortex entity descriptor.

### Entity descriptor

```yaml
x-cortex-alerts:
  - type: opsgenie
    tag: different-tag
    value: my-entity-override-tag
```

| Field   | Description                                       | Required |
| ------- | ------------------------------------------------- | :------: |
| `type`  | Type of alert (in this case, `opsgenie`)          |   **✓**  |
| `tag`   | Type of tag in Opsgenie (e.g. `backend`)          |   **✓**  |
| `value` | Alert in Opsgenie (e.g. `my-entity-override-tag`) |   **✓**  |

For example, for the tag `different-tag:my-entity-override-tag`, the entity descriptor would have `different-tag` in the **tag** field and `my-entity-override-tag` in the **value** field.

You can add a list of tags to use for lookup. Cortex will use an `OR` operator when querying Opsgenie (e.g. `backend:my-entity OR service:another-value`).

The `value` field also supports wildcards (e.g. `value: my-entity*`).

**Adding a schedule**

You can define the following block in an entity descriptor to add an Opsgenie schedule. Cortex supports adding a schedule by ID or UUID. You can add one schedule per entity.

The UUID for the schedule can be found in URL when viewing schedule details by clicking on the schedule name under who is on-call.

```yaml
x-cortex-oncall:
  opsgenie:
    type: SCHEDULE
    id: Cortex-Engineering
```

| Field  | Description                                               | Required |
| ------ | --------------------------------------------------------- | :------: |
| `type` | Opsgenie component being added (in this case, `SCHEDULE`) |   **✓**  |
| `id`   | Schedule ID or UUID                                       |   **✓**  |

#### Ownership

```yaml
x-cortex-owners:
  - type: group
    name: My Opsgenie Team
    provider: OPSGENIE
    description: This is a description for this owner
```

| Field         | Description                                               | Required |
| ------------- | --------------------------------------------------------- | :------: |
| `type`        | Ownership type (in this case, `group`)                    |   **✓**  |
| `name`        | Name of the team defined in Opsgenie (\*\*case-sensitive) |   **✓**  |
| `provider`    | Identity provider (in this case, `OPSGENIE`)              |   **✓**  |
| `description` | Description for the team, to be displayed in Cortex       |          |

#### Identity mappings

Cortex maps email addresses in your Opsgenie instance to email addresses that belong to team members in Cortex. When identity mapping is set up, users will be able to see their personal on-call status from the developer homepage.

## Using the Opsgenie integration

After setting up the integration, Opsgenie information will appear in several places across Cortex.

### Viewing on-call information for an entity

On an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details), current on-call information from Opsgenie will display in the **On-call** block.

Escalation policy, the level associated with the policy, and other on-call information will also appear in the entity's sidebar in the "On-call & incidents" page. Owners assigned to each level will also be hyperlinked to the user or team page in Opsgenie.

<figure><img src="/files/grNpdDVStmd2gyI9b7Qj" alt="On-call information appears on the right side of an entity details page."><figcaption></figcaption></figure>

### Viewing recent Opsgenie events

Click **Events** in an entity's sidebar to view recent events pulled in from Opsgenie.

### Viewing on-call information on the dev homepage

The Opsgenie integration enables Cortex to pull on-call information into the on-call block on the Dev homepage. On-call data from Opsgenie is refreshed every 1 minute.

### Scorecards and CQL

With the Opsgenie integration, you can create Scorecard rules and write CQL queries based on Opsgenie on-call schedules and alerts.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if on-call is set</summary>

Check if entity has a registered schedule.

**Definition:** `oncall (==/!=) null`

**Example**

For a Scorecard focused an production readiness, you can use this expression to make sure on-call is defined for entities:

```
oncall != null
```

This rule will pass if an entity has an on-call schedule set.

</details>

<details>

<summary>Number of alerts</summary>

Number of alerts for a given lookback period that match a given [search query](https://support.atlassian.com/opsgenie/docs/search-queries-for-alerts/).

**Definition:** `oncall.numOfAlerts(lookback=,query=).length`

**Example**

For a Scorecard focused on maturity or quality, you can use this expression to make sure a given entity has fewer than two alerts in the last month:

```
oncall.numOfAlerts(lookback=duration("P1M"),query="status: open").length < 2
```

You could also refine this rule by specifying priority level:

```
oncall.numOfAlerts(lookback=duration("P1M"),query="priority: P1").length < 2
```

Entities will pass this rule if they have fewer than 2 alerts with priority level "P1" in the last month.

</details>

<details>

<summary>Number of escalations</summary>

Number of escalation tiers in escalation policy.

**Definition:** `oncall.numOfEscalations()`

**Example**

This expression could be used in a Scorecard focused on production readiness or service maturity. For example, you can check that there are at least two tiers in an escalation policy for a given entity, so that if the first on-call does not ack, there is a backup:

```
oncall.numOfEscalations() >= 2
```

While making sure an on-call policy set is a rule that would be defined in a Scorecard's first level, a rule focused on escalation tiers would make more sense in a higher level.

</details>

<details>

<summary>On-call metadata</summary>

On-call metadata.

* ID
* Name
* Type

**Definition:** `oncall.details()`

**Example**

To find all entities without a schedule-type on-call registration, you can use this expression in the Query builder:

```
oncall.details().type =! "schedule"
```

If you're migrating on-call policies, you could use this rule to check for outdated policies. Let's say, for example, all outdated Opsgenie policies start with "Legacy" in their titles.

```
oncall.details().id.matches("Legacy*") == false
```

Entities with on-call policies that start with "Legacy" will fail, while those with other policy names will pass.

</details>

**Ownership CQL**

<details>

<summary>All ownership details</summary>

A special built-in type that supports a null check or a count check, used to enforce ownership of entities.

**Definition:** `ownership: Ownership | Null`

**Example**

An initial level in a security Scorecard might include a rule to ensure an entity has at least one team as an owner:

```
ownership.teams().length > 0
```

</details>

<details>

<summary>All owner details</summary>

List of owners, including team members and individual users, for each entity

**Definition:** `ownership.allOwners()`

**Example**

The Scorecard might include a rule to ensure that entity owners all have an email set:

```
ownership.allOwners().all((member) => member.email != null)
```

</details>

<details>

<summary>Team details</summary>

List of teams for each entity

**Definition:** `ownership.teams(): List<Team>`

**Example**

The Scorecard might include a rule to ensure that an entity owners all have a description and are not archived:

```
ownership.teams().all(team => team.description != null and team.isArchived == false)
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex performs the following background jobs:

* **Ownership**: A sync for Opsgenie teams every day at 9 a.m. UTC.
* **Identity mapping**: A sync for Opsgenie identities every day at 10 a.m. UTC.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# PagerDuty

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[PagerDuty](https://www.pagerduty.com/) is an incident response platform that allows developers to manage alerts, schedule rotations, define escalation policies, and more.

Integrating PagerDuty with Cortex allows you to:

* Pull in PagerDuty services, on-call schedules, and escalation policies
  * The on-call user or team will appear in the **Current On-call** block on an entity's details page.
  * You can also view on-call information on an entity page in its side panel under **Integrations > On-call**.
* [Trigger incidents in PagerDuty](#trigger-an-incident) directly from Cortex
* Automatically surface the most vital information about entity health and metadata when an incident is triggered by using [Cortex's On-Call Assistant tool](#enabling-the-on-call-assistant)
  * The On-Call Assistant automatically notifies users via Slack when an incident is triggered. The notifications include runbooks, links, dependencies, and key information about the affected entity.
* View incidents from PagerDuty in an entity's event timeline
* View on-call information from PagerDuty in the [engineering homepage](#engineering-homepage)
* Use PagerDuty metrics in [Eng Intelligence](#eng-intelligence) to understand key metrics and gain insight into services, incident response, and more.
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your on-call schedules and alerts

### How to configure PagerDuty with Cortex

### Prerequisites

Before getting started:

* Create a [PagerDuty API key](https://support.pagerduty.com/docs/generating-api-keys).
  * When adding the API key, you have the option to set `read` or `write` permissions.
    * **Read**: Enables Cortex to read any and all data from PagerDuty
    * **Write**: Allows users to [trigger incidents](#trigger-an-incident) from an entity page in Cortex, and enables On-Call Assistant
  * To use PagerDuty [blocks in a Workflow](/streamline/workflows/blocks#configure-an-integration-block) in Cortex, enable the following permissions:
    * `incident.write` to create incidents
    * `escalation_policies.write` to create escalation policies
    * `schedules.write` to create schedules
    * `services.write` to create services
    * `teams.write` to create teams

### Configure the integration in Cortex

1. In Cortex, navigate to the [PagerDuty settings page](https://app.getcortexapp.com/admin/integrations/pagerduty):
   * Click **Integrations** from the main nav. Search for and select **PagerDuty**.
2. Click **Add configuration**.
3. Configure the integration:
   * **API key**: Enter the API key you created in PagerDuty.
     * If the **Read-only API key** option is togged off, Cortex will use assume the provided API key has `write` permissions.
4. Click **Save**.

If you’ve set everything up correctly, you’ll see the option to **Remove Integration** in settings.

You can also use the **Test configuration** button to confirm that the configuration was successful. If your configuration is valid, you’ll see a banner that says “Configuration is valid. If you see issues, please see documentation or reach out to Cortex support.”

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## Enabling the On-call Assistant

At this stage, you can enable the Cortex On-call Assistant, which notifies users via Slack when an incident is triggered in PagerDuty. See the documentation for instructions: [On-Call Assistant](/ingesting-data-into-cortex/entities-overview/entities/oncall-assistant).

Note that On-Call Assistant will only work for [service-level PagerDuty registrations](#considerations-for-registering-pagerduty-entities) since these notifications are related to affected services.

## How to connect Cortex entities to PagerDuty

### Discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. my-entity) or its name as the "best guess" for PagerDuty services. For example, if your Cortex tag is my-entity, then the corresponding service in PagerDuty should also be my-entity.

If your PagerDuty services don’t cleanly match the Cortex tag or name, you can override this in the Cortex entity descriptor.

### Considerations for registering PagerDuty entities

Cortex recommends setting up PagerDuty at the service level by registering service entities with PagerDuty services, rather than configuring team entities with a PagerDuty schedule.

If PagerDuty is set up on a service level, you can see current on-call information listed within a given service's page. If PagerDuty is set up on the team level, you will only be able to view on-call rotation information from a team page.

Other benefits to setting up PagerDuty on a service level include:

* Structuring PagerDuty 1-1 with services enables better alert routing and analytics, something that organizations struggle more with when PagerDuty is set up on a team level.
* With a service-level setup, it’s easier to enforce all services to have a compliant on-call policy enacted in PagerDuty, especially when making use of Scorecards.
* The service-level setup is less reliant on team members tagging incidents with service information because services and incidents are already linked.
* You will gain the ability to get data from your Cortex catalog into PagerDuty, such as tier/criticality. By tying the service entities in the catalog with those in PagerDuty, you can automate processes and streamline severity protocols.

#### View on-call data only

If you want to only view on-call data for entities, and you do not want incidents displayed in Cortex, you can [register the escalation policy ID](#define-an-escalation-policy) for an entity.

### Editing the entity descriptor

For a given entity, you can define the PagerDuty service, schedule, or escalation policy within the entity’s YAML. **You can only set up one of these three options per entity.**

Each of these has the same field definitions.

| Field  | Description                                              | Required |
| ------ | -------------------------------------------------------- | :------: |
| `id`   | PagerDuty ID for service, schedule, or escalation policy |   **✓**  |
| `type` | `SERVICE`, `SCHEDULE` or `ESCALATION_POLICY`             |   **✓**  |

#### **Define a PagerDuty service**

Find the service ID value in PagerDuty under **Configuration > Services**. The URL for the service will contain the ID, for example: `https://cortexapp.pagerduty.com/services/`. You can only configure one service ID per entity.

```yaml
x-cortex-oncall:
  pagerduty:
    id: ASDF1234
    type: SERVICE
```

#### **Define a schedule**

Find a schedule ID in PagerDuty under **People > On-call schedules**. Click the desired schedule to view its ID in the URL, for example: `https://cortexapp.pagerduty.com/schedules#`. You can only configure one schedule per entity.

```yaml
x-cortex-oncall:
  pagerduty:
    id: ASDF1234
    type: SCHEDULE
```

#### **Define an escalation policy**

Find the escalation policy ID in PagerDuty under **People > Escalation Policies**. Click the desired policy to view its ID in the URL, for example: `https://cortexapp.pagerduty.com/escalation_policies#`. You can only configure one escalation policy per entity.

When linking a Cortex entity to a PagerDuty escalation policy, only on-call information will be surfaced in Cortex — incidents will not be shown. This is a useful alternative for teams that want to suppress incident visibility while displaying call schedules.

```yaml
x-cortex-oncall:
  pagerduty:
    id: ASDF1234
    type: ESCALATION_POLICY
```

{% hint style="warning" %}
You can only set up one of the three options above per entity.
{% endhint %}

### Identity mappings

Cortex maps email addresses in your PagerDuty instance to email addresses that belong to team members in Cortex. When [identity mapping](/configure/settings/managing-users/identity-mapping) is set up, users will be able to see their personal on-call status from the developer homepage.

## Using the PagerDuty integration

#### Entity pages

Once the PagerDuty integration is set up, you’ll be able to view current on-call information in the "on-call" block on an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details). In the left sidebar of an entity, click **On-call & incidents** to view on-call information, escalation policy, service, and incidents.

The escalation policy and PagerDuty service details are hyperlinked to the corresponding pages in your PagerDuty instance.

Click **Events** in an entity's sidebar to view recent events pulled in from PagerDuty.

#### Engineering homepage

The PagerDuty integration enables Cortex to pull on-call information into the on-call block on the [Engineering homepage](/streamline/homepage). On-call data from PagerDuty is refreshed every 60 minutes.

#### Eng Intelligence

Cortex also pulls in metrics from PagerDuty for [Eng Intelligence](/improve/eng-intelligence). This tool will display MTTR, incidents opened, and incidents opened per week.

#### Retrieve on-call information in Slack

If you have a Slack integration set up, you can also use the `/cortex oncall` [Slack Bot command](/ingesting-data-into-cortex/integrations/slack#cortex-bot) to retrieve current on-call information. This feature works for both services and teams with registered PagerDuty schedules or escalation policies.

#### Scorecards and CQL

With the PagerDuty integration, you can create Scorecard rules and write CQL queries based on incidents, escalations, and on-call metadata.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if on-call is set</summary>

Check if entity has a registered service, schedule, or escalation policy. If the service does not have any registrations in its entity descriptor, Cortex searches for PagerDuty services matching the tag defined in the entity's `x-cortex-tag` field.

**Definition:** `oncall (==/!=) null`

**Example**

For a Scorecard focused an production readiness, you can use this expression to make sure on-call is defined for entities:

```
oncall != null
```

This rule will pass if an entity has a service, schedule, or escalation policy set.

</details>

<details>

<summary>Forbidden contact methods</summary>

Number of users in each entity's escalation policy with missing or forbidden contact methods.

Allowed contact methods:

* "SMS"
* "PHONE"
* "EMAIL"
* "PUSH\_NOTIFICATION"
* "SLACK"

**Definition:** `oncall.usersWithoutContactMethods(allowed=<allowed>, onlyCurrentOncall=<boolean>).length`

**Example**

For a Scorecard focused on ownership, you can use this expression to make sure users have required contact methods enabled:

```
oncall.usersWithoutContactMethods(allowed=["SMS", "PHONE"]).length == 0
```

This rule will pass if every user in an associated escalation policy has either SMS or phone calls enabled as their contact method.

You can also use this expression in the Query builder to find users that lack the required contact method:

```
oncall.usersWithoutContactMethods(allowed=["EMAIL"]) > 0
```

This query will surface users without email addresses.

If you want to check only current on-call users, you can use the `onlyCurrentOncall` parameter:

```
oncall.usersWithoutContactMethods(allowed=["EMAIL"], onlyCurrentOncall=true) > 0
```

When this parameter is set to `false` or omitted, the expression will check all users in the associated escalation policy for the next 3 months.

</details>

<details>

<summary>Incident response analysis</summary>

Get detailed [on-call analysis stats](https://developer.pagerduty.com/api-reference/694e92fe4f943-get-aggregated-service-data) for each entity:

* Mean assignment count
* Mean engaged seconds
* Mean engaged user count
* Mean seconds to engage
* Mean seconds to first ack
* Mean seconds to mobilize
* Mean seconds to resolve
* Total business-hour erruptions
* Total engaged seconds
* Total escalation count
* Total off-hour erruptions
* Total sleep-hour erruptions
* Total snoozed seconds
* Total incident count
* Up time percent

PagerDuty updates its analytics data once per day, and it can take up to 24 hours before new incidents appear in the analytics API.

**Only works if entity has a registered PagerDuty service ID or if the PagerDuty service name matches the entity tag.**

**Definition:** `oncall.analysis(lookback = <duration>, priority = <List<String>>)`

**Examples**

PagerDuty analytics can easily be used to craft rules for a DORA metrics Scorecard.

For mean time to acknowledge, you can use the `meanSecondsToFirstAck` schema definition:

```
oncall.analysis(lookback = duration("P7D"), priority = ["P1", "P2"]).meanSecondsToFirstAck <= 300
```

Entities will pass this rule if incidents in the last week were acknowledged within 5 minutes.

For mean time to resolve, you can use `meanSecondsToResolve` to make sure that incidents were handled within an hour:

```
oncall.analysis(lookback = duration("P7D"), priority = ["P1"]).meanSecondsToResolve < 3600
```

You can also use this expression to write a rule checking entities' change failure rate:

```
oncall.analysis(lookback = duration("P7D")).totalIncidentCount == 0
```

This rule will pass if there weren't any incidents in the last week.

</details>

<details>

<summary>Incidents</summary>

Get incident data for each entity:

* Assignee ID
* Created at
* Incident ID
* Last updated
* Resolved at
* Service ID
* Status

**Only works if entity has a registered PagerDuty service ID or if the PagerDuty service name matches the entity tag.**

**Definition:** `oncall.incidents(lookback = <duration>)`

**Examples**

For a Scorecard focused on service maturity or quality, you can use this expression to check the number of incidents opened in the last month:

```
oncall.incidents(lookback = duration("P1M")).length < 15
```

Entities will pass this rule if they have fewer than 15 incidents opened in the last month.

You can also use this expression to make sure there aren't incidents that remain open over the last month:

```
oncall.incidents(lookback=duration("P1M")).filter((incident) => incident.status.matches("TRIGGERED|ACKNOWLEDGED")).length < 1
```

Or you can check for incidents that took a certain amount of time to resolve:

```
oncall.incidents(lookback=duration("P1M")).filter((incident) => incident.createdAt.until(incident.resolvedAt) > duration("P-2D")).length < 2
```

Entities will pass this rule if there were 0 or 1 incidents in the last month that took more than 2 days to resolve.

</details>

<details>

<summary>Number of escalations</summary>

Number of escalation tiers in escalation policy.

**Definition:** `oncall.numOfEscalations()`

**Example**

This expression could be used in a Scorecard focused on production readiness or service maturity:

```
oncall.numOfEscalations() >= 2
```

This rule checks that there are at least two tiers in an escalation policy for a given entity, so that if the first on-call does not ack, there is a backup.

While making sure an on-call policy set is a rule that would be defined in a Scorecard's first level, a rule focused on escalation tiers would make more sense in a higher level.

</details>

<details>

<summary>On-call metadata</summary>

On-call metadata, including type, id, and name.

**Definition:** `oncall.details()`

**Examples**

To find all entities with a schedule-type on-call registration, you can use this expression in the Query builder:

```
oncall.details().type == "schedule"
```

If you're migrating on-call policies, you could use this rule to check for outdated policies. Let's say, for example, all outdated PagerDuty policies start with "Legacy" in their titles.

```
oncall.details().id.matches("Legacy*") == false
```

Entities with on-call policies that start with "Legacy" will fail, while those with other policy names will pass.

</details>

### Trigger an incident

As described above under [Editing the entity descriptor](#editing-the-entity-descriptor), a given entity can have a PagerDuty service, schedule, or escalation policy defined. Only entities with a PagerDuty service defined will include the option to trigger an incident directly from Cortex.

Your PagerDuty API key must include the `write` permission in order to trigger incidents from an entity.

While viewing an entity in Cortex, follow these steps to trigger an incident in PagerDuty:

1. In Cortex, navigate to an entity. On the left side of an entity details page, click **On-call & incidents**.
2. In the upper right side of the entity's "On-call" page, click **Trigger incident**.
3. Configure the incident modal:
   * **Summary**: Enter a title for the incident.
   * **Description**: Enter a description of the incident.
   * **Severity**: Select a severity level.
4. At the bottom of the modal, click **Trigger incident**.
   * A confirmation screen will appear. In the confirmation, click the link to view the incident in PagerDuty.

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

PagerDuty performs the following background jobs:

* **On-call:** On-call information displayed on the developer homepage is refreshed **every 60 minutes**.
* **Services and incidents:** Services used for automapping and active incidents viewable in the catalog are fetched approximately **every 5 minutes**, or however long the refresh takes.
* **Users**: User data for identity mapping is synced daily at 10 a.m. UTC.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Prometheus

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

## Overview

[Prometheus](https://prometheus.io/) is an open-source monitoring and analytics platform that allows customers to analyze, visualize, automate, and alert on metrics data.

Integrating Cortex with Prometheus allows you to:

* [View SLO information](#view-prometheus-data-in-entity-pages) from Prometheus on entity pages in Cortex
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving Prometheus SLOs

## How to configure Prometheus with Cortex

There are two options for integrating Prometheus: the default configuration method and Cortex Axon Relay, a relay broker allows you to securely connect your on-premises Prometheus data.

### Prerequisite

Before getting started, set up [basic authentication](https://prometheus.io/docs/guides/basic-auth/) credentials in Prometheus.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

{% tabs %}
{% tab title="Default configuration" %}
**Configure the integration in Cortex**

1. In Cortex, navigate to the [Prometheus settings page](https://app.getcortexapp.com/admin/integrations/prometheus):
   * Click **Integrations** from the main nav. Search for and select **Prometheus**.
2. Click **Add integration**.
3. Configure the Prometheus integration form:
   * **Account alias**: Enter your account alias.
   * **Username** and **Password**: Enter your Prometheus basic auth credentials.
   * **Host**: Enter your self-managed Prometheus hostname.
   * **Tenant ID**: Optionally, enter your tenant ID.
     * If you have multiple tenants, you can enter an ID here to monitor a specific tenant.
4. Click **Save**.
   {% endtab %}

{% tab title="Relay broker" %}
**Configure Prometheus with Cortex Axon Relay**

See [Internally hosted integrations](/ingesting-data-into-cortex/integrations/axon-relay) for instructions. Make sure to follow the Prometheus-specific instructions for the docker-compose.yml file.
{% endtab %}
{% endtabs %}

**Configure the integration for multiple Prometheus accounts**[**​**](https://docs.cortex.io/docs/reference/integrations/prometheus#configure-the-integration-for-multiple-propsintegration-accounts)

The Prometheus integration has multi-account support. You can add a configuration for each additional by repeating the process above.

Each configuration requires an alias, which Cortex uses to correlate the designated with registrations for various entities. Registrations can also use a default configuration without a listed alias. You can edit aliases and default configurations from the Prometheus page in your Cortex settings. Select the edit icon next to a given configuration and toggle **Set as default** on. If you only have one configuration, it will automatically be set as the default.

## Connecting Cortex entities to Prometheus

### Linking SLOs in Cortex

You can create and manage SLOs by listing relevant SLIs through queries.

```yaml
x-cortex-slos:
  prometheus:
    - errorQuery: sum(rate(http_server_requests_seconds_count{code=~"(5..|429)"}[5m]))
      totalQuery: sum(rate(http_server_requests_seconds_count[5m]))
      slo: 99.95
      alias: my-prometheus-instance # alias is optional and only relevant if you have opted into multi account support
      name: my-slo-name
```

| Field      | Description                                                                                                                                                                                                         |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| errorQuery | Query that indicates error events for your metric.                                                                                                                                                                  |
| totalQuery | Query that indicates all events to be considered for your metric.                                                                                                                                                   |
| slo        | Target number for SLO.                                                                                                                                                                                              |
| alias      | Ties the SLO registration to a Prometheus instance listed under Settings → Prometheus. The alias parameter is optional, but if not provided the SLO will use the default configuration under Settings → Prometheus. |
| name       | The SLO's name in Prometheus. The name parameter is optional.                                                                                                                                                       |

### How Cortex calculates Prometheus SLOs

When Cortex gets an SLO from Prometheus, the following query is calculated for it:

```
(1 - ({errorQuery}) / ({totalQuery}))
```

This value is calculated and resolved on an hour window, and calculated back for 7 days. Cortex averages the value for each 1-hour window, then averages each of those hourly averages across the lookback period, before displaying it in your Cortex workspace.

The value is updated when the entity page is loaded and when Scorecards are evaluated.

## Using the Prometheus integration

### View Prometheus data in entity pages

When an SLO is defined in an entity's descriptor, you'll see detailed data about SLOs in the **Monitoring** page in the sidebar of an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details). See the SLO query, target, the current value for each SLO, and the period of time the SLO is being calculated for. For example, if the time listed is "7 days ago," then the SLO is looking at the time range starting 7 days ago to now\..

### Scorecards and CQL

With the Prometheus integration, you can create Scorecard rules and write CQL queries based on Prometheus SLOs.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>SLOs</summary>

SLOs associated with the entity via ID or tags. You can use this data to check whether an entity has SLOs associated with it, and if those SLOs are passing.

**Definition:** `slos: List<SLO>`

**Examples**

In a Scorecard, you can use this expression to make sure an entity is passing its SLOs:

```
slos().all((slo) => slo.passing) == true
```

Use this expression to make sure latency Service Level Indicator (SLI) value is above 99.99%:

```
slos().filter((slo) => slo.name.matchesIn("latency") and slo.sliValue >= 0.9999).length > 0
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Rollbar

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Rollbar](https://rollbar.com/) is an error tracking tool that helps developers discover and resolve crashes and errors.

Integrating Rollbar with Cortex allows you to:

* [View errors on entity pages in Cortex](#viewing-rollbar-errors-on-an-entity), giving you insight into your entity's operational maturity
* Create [Scorecards](#scorecards-and-cql) that include rules relating to error data from Rollbar, motivating team members to improve their code quality

## How to configure Rollbar with Cortex

### Prerequisites

Before getting started:

* Create a [Rollbar access token](https://explorer.docs.rollbar.com/#section/Authentication/Account-Access-Tokens).
  * The token requires `read` permissions at minimum. This allows Cortex to automatically look up project tokens for each Rollbar project and attempt to reuse them to access project details.
  * Granting the token `read` and `write` permissions enables Cortex to automatically create an access token if none exists for a given project.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Rollbar settings page](https://app.getcortexapp.com/admin/integrations/rollbar):
   1. Click **Integrations** from the main nav. Search for and select **Rollbar**.
2. Click **Add configuration**.
3. Configure the integration form:
   * **Account access token**: Enter the access token you generated in Rollbar.
   * **Account name**: Enter your Rollbar account name, found in your Rollbar settings.
     * The name also appears in the URL for your Rollbar instance, e.g.,
4. Click **Save**.

After saving your configuration, you are redirected to the Rollbar integration settings page in Cortex. In the upper right corner of the page, click **Test configuration** to ensure Rollbar was configured properly.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Rollbar projects

### Discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) as the "best guess" for Rollbar projects. For example, if your Cortex tag is `my-entity`, then the corresponding project in Rollbar should also be `my-entity`.

If your Rollbar projects don’t cleanly match the Cortex tag, you can override this in the Cortex entity descriptor.

### Editing the entity descriptor

You can define projects under the `x-cortex-rollbar` block in an [entity's YAML](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file):

```yaml
x-cortex-rollbar:
  project: my-project
```

| Field     | Description                        | Required |
| --------- | ---------------------------------- | :------: |
| `project` | Project name as defined in Rollbar |   **✓**  |

## Using the Rollbar integration

### Viewing Rollbar errors on an entity

Error data from Rollbar will appear on an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details). In an entity's sidebar, click **Error tracking** to view detected issues for each Rollbar project. At the top of the page, see the associated project tag and the project framework.

Under **Items**, see a list of detected errors and their statuses. Next to the error name, you can also see badges for `# seen` and the type of event: `error`, `warning`, or `info`.

### Scorecards and CQL

With the Rollbar integration, you can create Scorecard rules and write CQL queries based on Rollbar projects.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Rollbar project is set</summary>

Check if entity has a registered Rollbar project.

**Definition:** `rollbar (==/!=) null`

**Example**

You can define a rule in an operational readiness Scorecard to make sure each entity has a registered Rollbar project.

```
rollbar != null
```

This is also a good way to confirm the integration is synced and reporting frequently.

You could also query for entities that don't have a registered Rollbar project to quickly identify those that need to be updated:

```
rollbar == null
```

</details>

<details>

<summary>RQL query</summary>

Evaluate an [RQL](https://docs.rollbar.com/docs/rql) query for the Rollbar project.

If the entity does not have a Rollbar project set, the rule will fail. An empty result set will result in null.

**Definition:** `rollbar.rql(<query>)`

**Example**

An operational maturity Scorecard, you can use this expression to make sure entities have fewer than 100 open errors.

```
rollbar.rql("SELECT count(*) FROM item_occurrence WHERE status = 1") < 100
```

Or you can set a rule that gauges errors over time:

```
rollbar.rql("SELECT count(*) / 30 FROM item_occurrence WHERE timestamp > unix_timestamp() - 60 * 60 * 24 * 30") < 5
```

This rule checks that entities have fewer than 5 new errors per day on average over the last 30 days.

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Rootly

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Rootly](https://rootly.com/) is an on-call and incident response platform.

Integrating Rootly with Cortex allows you to:

* [Trigger an incident](#trigger-an-incident) directly from Cortex
* [View incident data](#viewing-incidents-in-cortex) on entity pages in Cortex
  * When active incidents are detected in Rootly, Cortex will display incident information on an entity's details page in the **Overview** and **Operations** tabs.
* Create [Scorecards](/standardize/scorecards) that track progress and drive alignment on projects involving incidents

## How to configure Rootly with Cortex[​](https://docs.cortex.io/docs/reference/integrations/rootly#how-to-configure-rootly-with-cortex) <a href="#how-to-configure-rootly-with-cortex" id="how-to-configure-rootly-with-cortex"></a>

### Prerequisites[​](https://docs.cortex.io/docs/reference/integrations/rootly#prerequisites) <a href="#prerequisites" id="prerequisites"></a>

Before getting started:

* Create an [API token in Rootly](https://rootly.com/api#/). Ensure the Rootly user account represented by the API key has admin permissions in Rootly.

### Configure the integration in Cortex[​](https://docs.cortex.io/docs/reference/integrations/rootly#configure-the-integration-in-cortex) <a href="#configure-the-integration-in-cortex" id="configure-the-integration-in-cortex"></a>

1. In Cortex, navigate to the [Rootly settings page](https://app.getcortexapp.com/admin/integrations/rootly):
   * Click **Integrations** from the main nav. Search for and select **Rootly**.
2. Click **Add configuration**.
3. Configure the Rootly integration form:
   * **Account alias**: Enter the alias for your configuration.
   * **API token**: Enter your Rootly API token.
4. Click **Save**.

Once you save your configuration, you'll see it listed on the integration's settings page in Cortex. If you’ve set everything up correctly, you’ll see the option to **Remove Integration** in Settings.

You can also use the **Test all configurations** button to confirm that the configuration was successful. If your configuration is valid, you’ll see a banner that says “Configuration is valid. If you see issues, please see documentation or reach out to Cortex support.”

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

**Configure the integration for multiple Rootly accounts**[**​**](https://docs.cortex.io/docs/reference/integrations/rootly#configure-the-integration-for-multiple-propsintegration-accounts)

The Rootly integration has multi-account support. You can add a configuration for each additional instance by repeating the process above.

Each configuration requires an alias, which Cortex uses to correlate the designated instance with registrations for various entities. Registrations can also use a default configuration without a listed alias. You can edit aliases and default configurations from the Rootly page in your Cortex settings. Select the edit icon next to a given configuration and toggle **Set as default** on. If you only have one configuration, it will automatically be set as the default.

## Viewing incidents in Cortex[​](https://docs.cortex.io/docs/reference/integrations/rootly#viewing-incidents-in-cortex) <a href="#viewing-incidents-in-cortex" id="viewing-incidents-in-cortex"></a>

You can view incidents on an entity details page. Each incident is listed with its title, severity, status, and description.

To view the list of incidents:

1. In Cortex, navigate to an entity.
2. On the left side of the entity details page, click **On-call & incidents**.
3. In the list, view all incidents from the last 30 days. To narrow the list by severity or or status, use the filters at the top of the page.

In addition, active incidents will appear at the top of the [entity details overview page](/ingesting-data-into-cortex/entities-overview/entities/details).

## How to connect Cortex entities to Rootly[​](https://docs.cortex.io/docs/reference/integrations/rootly#how-to-connect-cortex-entities-to-rootly) <a href="#how-to-connect-cortex-entities-to-rootly" id="how-to-connect-cortex-entities-to-rootly"></a>

### Discovery[​](https://docs.cortex.io/docs/reference/integrations/rootly#discovery) <a href="#discovery" id="discovery"></a>

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) or entity name as the "best-guess" for a Rootly service. For example, if your Cortex tag is `my-entity`, then the corresponding service slug in Rootly should also be `my-entity`.

If your Rootly service name does not match the Cortex tag or name, you can override this in the Cortex entity descriptor.

#### Editing the entity descriptor[​](https://docs.cortex.io/docs/reference/integrations/rootly#editing-the-entity-descriptor) <a href="#editing-the-entity-descriptor" id="editing-the-entity-descriptor"></a>

For a given entity, you can define Rootly services by ID or slug.

| Field  | Description  | Required |
| ------ | ------------ | -------- |
| `id`   | Service ID   | \*\*\*\* |
| `slug` | Service slug | \*\*\*\* |

#### **Service ID**

```yaml
x-cortex-rootly:
  services:
    - id: ASDF1234
```

#### **Service slug**

```yaml
x-cortex-rootly:
  services:
    - slug: service-slug
```

## Using the Rootly integration <a href="#trigger-an-incident" id="trigger-an-incident"></a>

### Trigger an incident[​](https://docs.cortex.io/docs/reference/integrations/rootly#trigger-an-incident) <a href="#trigger-an-incident" id="trigger-an-incident"></a>

While viewing an entity in Cortex, you can trigger an incident in Rootly:

1. In Cortex, navigate to an entity. On the left side of an entity details page, click **Integrations > Rootly**.
2. In the upper right side of the entity's Rootly page, click **Trigger incident**.
3. Configure the incident modal:
   * **Name**: Enter a name for the incident.
   * **Summary**: Enter a summary for the incident.
   * **Description**: Enter a long-form description of the incident.
   * **Severity**: Select a severity level.
   * **Condition**: Select a condition for the incident.
4. At the bottom of the modal, click **Trigger incident**.
   * A confirmation screen will appear. In the confirmation, click the link to view the incident in Rootly.

### Scorecards and CQL[​](https://docs.cortex.io/docs/reference/integrations/rootly#scorecards-and-cql) <a href="#scorecards-and-cql" id="scorecards-and-cql"></a>

With the Rootly integration, you can create Scorecard rules and write CQL queries based on Rootly incidents.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Rootly service is set</summary>

Check if entity has a registered Rootly service in its entity descriptor.

If no registration exists, Cortex will try to automatically detect which corresponding Rootly service name or tag is associated with the entity.

**Definition:** `rootly (==/!=) null`

**Example**

For a Scorecard focused on operational maturity, you can use this expression to make sure each entity has an Rootly service set:

```
rootly != null
```

</details>

<details>

<summary>Incidents</summary>

List incidents, filterable by severity and status.

* Created at
* Mode
* Name
* Severity
* Status
* Summary
* Type
* URL

**Definition:** `rootly.incidents()`

**Example**

To assess entities' health in a Scorecard, you can write a rule to make sure a given entity has fewer than three incidents with a severity of SEV1:

```
rootly.incidents(severity = ["SEV1"]).length < 3
```

You can also use this expression to query for entities that have two or fewer critical incidents in the last three months:

```
  rootly.incidents(severity = ["Critical"]).filter((incident) => incident.createdAt.fromNow() > duration("-P90D")).length <= 2
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Sentry

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Sentry](https://sentry.io/welcome/) is an application monitoring platform that helps developers identify, debug, and resolve issues.

Integrating Sentry with Cortex allows you to:

* [View errors on entity pages in Cortex](#viewing-sentry-errors-on-an-entity), giving you insight into your entity's operational maturity
* [Pull a list of recent Sentry issues directly in Slack](#using-the-cortex-slack-bot-with-sentry), using the Cortex Slack Bot
* Create [Scorecards](#scorecards-and-cql) that include rules related to Sentry errors

## How to configure Sentry with Cortex

### Prerequisites

Before getting started:

* Create a [personal token](https://docs.sentry.io/api/auth/#user-authentication-tokens) in your Sentry user settings.
  * The token requires `Read` [permissions](https://docs.sentry.io/api/permissions/) for the **Issue & Event** and **Project** scopes.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Sentry settings page](https://app.getcortexapp.com/admin/integrations/sentry):
   * Click **Integrations** from the main nav. Search for and select **Sentry**.
2. Click **Add configuration**.
3. Configure the integration form:
   * **Auth token**: Enter the personal token you generated in Sentry.
   * **Organization slug**: Enter your Sentry organization slug.
     * You can find this in your Sentry URL, e.g., `https://sentry.io/organizations/{SLUG}/issues/`.
   * **Host**: If using a self-hosted Sentry instance, enter the URL here *without* the API path (e.g., `bugsnag.getcortexapp.com`).
4. Click **Save**.

After saving your configuration, you are redirected to the Sentry integration settings page in Cortex. In the upper right corner of the page, click **Test configuration** to ensure Sentry was configured properly.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Sentry projects

### Discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g., `my-entity`) as the best guess for Sentry projects. For example, if your Cortex tag is `my-entity`, then the corresponding project in Sentry should also be `my-entity`.

If your Sentry projects don't cleanly match the Cortex tag, you can override this in the Cortex entity descriptor.

### Editing the entity descriptor

You can define projects under the `x-cortex-sentry` block:

```yaml
x-cortex-sentry:
  projects:
  - name: my-project
  - name: my-second-project
```

| Field  | Description                                                                          | Required |
| ------ | ------------------------------------------------------------------------------------ | :------: |
| `name` | <p>Project ID or slug defined in Sentry.</p><p>Note that this is case sensitive.</p> |   **✓**  |

## Using the Sentry integration

### Viewing Sentry errors on an entity

Error data will appear on an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details). In an entity's sidebar, click **Error tracking** to view detected issues for each Sentry project. At the top of the page, see a list of Sentry projects associated with an entity. Each project listed in Cortex links back to the [project details page in Sentry](https://docs.sentry.io/product/projects/project-details/).

Under the **Issues** header on the **Error tracking** page, you'll find a list of all issues related to the projects that Cortex detected in Sentry. Each issue in the list links back to that [issue's details page in Sentry](https://docs.sentry.io/product/issues/issue-details/). Cortex will pull in the title and tags for each issue.

**Events**

Sentry issues and events will also appear in an entity's event timeline, found under **Events** in the sidebar. This allows users to contextualize Sentry issues with other key data - like deploys or errors discovered from other integrations - during incidents or migrations.

### Using the Cortex Slack Bot with Sentry

If you have also configured the [Slack integration](/ingesting-data-into-cortex/integrations/slack), you can use the command `/cortex sentry <tag>` in [Slack](/ingesting-data-into-cortex/integrations/slack) to get a list of all recent Sentry issues for a given entity. `tag` is the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag).

### Scorecards and CQL

With the Sentry integration, you can create Scorecard rules and write CQL queries based on Sentry projects.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Sentry project is set</summary>

Check if entity has a registered Sentry project.

**Definition:** `sentry (==/!=) null`

**Example**

For a production readiness Scorecard, you can use this expression to make sure entities are linked to a Sentry project.

```
sentry != null
```

This can also serve as a way to confirm that entities are synced with Sentry and reporting frequently.

</details>

<details>

<summary>Number of events</summary>

Counts Sentry events for a given [custom query](https://docs.sentry.io/concepts/search/#query-syntax) **to a max of 1,000**.

If no query is provided, the rule will count `unresolved` events by default.

**Definition:** `sentry.numOfIssueEvents((<query>))`

**Example**

For a Scorecard focused on operational maturity, you can check for any unresolved issues that were first seen within a week.

```
sentry.numOfIssueEvents("is:unresolved firstSeen:-1w") <= 10
```

</details>

<details>

<summary>Number of issues</summary>

Counts Sentry issues for a given custom query **to a max of 300**.

If no query is provided, the rule will count `unresolved` issues by default.

**Definition:** `sentry.numOfIssues((<query>))`

**Example**

For a Scorecard focused on operational maturity, you can pull in the number of Sentry issues to make sure entities are functioning as expected.

```
sentry.numOfIssues() < 100
```

For a Scorecard focused on code quality, you can write a more focused rule to make sure there haven't been any issues in production environments in the last week.

```
sentry.numOfIssues("is:unresolved environment:[production,prod] lastSeen:-1w") < 2
```

\\

</details>

{% hint style="warning" %}
The maximum number of Sentry events fetched for any query is 1,000, while the maximum number of issues fetched is 300.
{% endhint %}

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Semgrep

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Semgrep](https://semgrep.dev/) is static application security testing (SAST) tool that includes software composition analysis (SCA). It detects security vulnerabilities in your code and analyzes your open-source dependencies for vulnerabilities. You can use it to scan local repositories or integrate it into your CI/CD pipeline.

Integrating Semgrep with Cortex allows you to:

* Display the latest scans and vulnerability data [on entity details pages in Cortex](#viewing-semgrep-information-in-cortex)
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving Semgrep security data, allowing you to address and remediate vulnerabilities more efficiently

## How to configure Semgrep with Cortex

### Prerequisites

Before getting started:

* Create an [API token in Semgrep](https://semgrep.dev/api/v1/docs/#section/Introduction) with [`GET scan details`](https://semgrep.dev/api/v1/docs/#tag/Scan/operation/semgrep_app.foundations.scan.handlers.scan.openapi_get_scan) and [`GET List code or supply chain findings`](https://semgrep.dev/api/v1/docs/#tag/Finding) permissions.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Semgrep settings page](https://app.getcortexapp.com/admin/integrations/semgrep):
   * Click **Integrations** from the main nav. Search for and select **Semgrep**.
2. Click **Add configuration**.
3. Configure the Semgrep integration form:
   * **Alias**: Enter an alias for this integration.
   * **API key**: Enter the value of the API token you created in Semgrep.
   * **Organization ID**: Enter your organization ID for Semgrep.
   * **Organization slug**: Enter your organization slug for Semgrep.
4. Click **Save**.

After saving your configuration, you are redirected to the Semgrep integration settings page in Cortex. In the upper right corner of the page, click **Test configuration** to ensure Semgrep was configured properly.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Semgrep

### Match entity names to Semgrep projects

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-service`) as the "best guess" for Semgrep projects. For example, if your entity name is "My Service" or your tag is `my-service`, then the corresponding project name in Semgrep should also be "My Service" or `my-service`.

If your Semgrep project names don’t cleanly match the Cortex entity name or tag, you can override this in the Cortex entity descriptor.

### Editing the entity descriptor

Under the `x-cortex-semgrep` block in an [entity's YAML](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file), you can define the projects you want based on the Semgrep project ID. For example:

```yaml
x-cortex-semgrep:
  projects:
  - alias: my_org 
    projectId: 1234567
  - alias: other_org
    projectId: 7654321
```

## Using the Semgrep integration

### Viewing Semgrep information in Cortex

Semgrap vulnerabilities and scans appear on [entity details pages](/ingesting-data-into-cortex/entities-overview/entities/details):

* in the **Code & security** block in the entity's overview:\\

  <div align="left"><figure><img src="/files/PtTMtvQJzvhdxvsM4ANx" alt="See Semgrep data on an entity&#x27;s overview." width="563"><figcaption></figcaption></figure></div>
* in the entity's sidebar in **Code & security.**

  * This page contains scan results and vulnerability metrics from Semgrep. Click **Filter** at the top of the vulnerability list to filter by severity.

  <div align="left"><figure><img src="/files/JDWBQKu5jEtwR3s9lsss" alt="On an entity, click Code &#x26; security > Semgrep to view vulnerability details from Semgrep." width="563"><figcaption></figcaption></figure></div>

### Scorecards and CQL

With the Semgrep integration, you can create Scorecard rules and write CQL queries based on Semgrep projects.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Semgrep project is set</summary>

Check if entity has a registered Semgrep project in its entity descriptor.

**Definition:** `semgrep (==/!=) null: Boolean`

**Example**

An initial level in a security Scorecard might include a rule to make sure entities are associated with a Semgrep project:

```
semgrep != null
```

Setting a `semgrep != null` rule can also serve as a secondary check to confirm an entity is synced properly with Semgrep and is reporting frequently.

</details>

<details>

<summary>List vulnerabilities</summary>

List of Semgrep vulnerabilities by severity or type.

**Definition:** `semgrep.vulnerabilities()`

**Example**

You can write a rule to verify an entity has fewer than 10 vulnerabilities:

```
semgrep.vulnerabilities().length < 10
```

</details>

<details>

<summary>Get scan results for an entity</summary>

Get Semgrep scan results for an entity.

**Definition**: `semgrep.scans()`

You could write a Scorecard rule to ensure an entity has fewer than 10 scans:

```
semgrep.scans().length < 10
```

You could write a rule to ensure an entity has had fewer than 10 new scans in the last week:

```
semgrep.scans("firstSeen:-1w") <= 10
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# ServiceNow

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[ServiceNow](https://www.servicenow.com/) is a CMDB (configuration management database) to define, manage, automate and structure IT services. Cortex integrates with ServiceNow to provide engineers with better developer experience while adhering to governance standards. The integration syncs data between systems so both stay current.

Integrating your ServiceNow instance with Cortex allows you to:

* [Import teams](#configuring-ownership-for-your-servicenow-entities) from ServiceNow and track ownership of entities
* [Automatically import domains and domain relationships](#enable-automated-discovery-of-domains-for-servicenow) from ServiceNow
* [Create Workflows](#workflows) to trigger ServiceNow actions, create tickets, or update records.
* [Use the ServiceNow Incidents plugin](#servicenow-incidents-plugin) to view ServiceNow incidents directly on entity details pages.
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your ServiceNow teams

{% hint style="success" %}
Some Cortex users link business applications to ServiceNow projects, creating a clear map of ownership and project alignment. This enables visibility into which projects tie to which business apps, helping track migrations, risk programs, and compliance projects.
{% endhint %}

## How to configure ServiceNow with Cortex

### Prerequisites

Your ServiceNow user must have the `sn_cmdb_user` permission enabled.

You must have the `Configure Integrations` [permission](/configure/settings/managing-users/permissioning) in Cortex.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

### Step 1: Configure the integration in Cortex

1. In Cortex, navigate to the [ServiceNow settings page](https://app.getcortexapp.com/admin/integrations/servicenow):
   * Click **Integrations** from the main nav. Search for and select **ServiceNow**.
2. Click **Add configuration**.
3. Configure the ServiceNow integration form:
   * **Instance name**: Enter your instance identifier.
     * This can be found in your instance URL, e.g., `<instance-identifier>.service-now.com`.
   * **Username** and **Password**: Enter your ServiceNow username and password.
4. Click **Save**.

Stay on this page for the next steps.

### Step 2: Configure table mappings

1. On the ServiceNow integrations settings page, click **Add table mapping** on the right.
2. Configure the "Add table mapping" form:

   * Choose a mapping type: Select whether your data will map to Domains, Services or Teams.

   <div align="left"><figure><img src="/files/OxsRFwVLz1oinrVgVfZC" alt="" width="512"><figcaption></figcaption></figure></div>

   * **Table name**: Enter a descriptive name.
   * **Table filter query**: Optionally, enter a table filter query.
   * **ID column name**: Enter the column name that contains the ID of the record.
   * **Name column name**: Enter the column name that contains the name of the record.
   * **Description column name**: Enter the column name that contains the description of the record.

   <div align="left"><figure><img src="/files/By7lQ6kqettA2Sz2MHMK" alt="" width="375"><figcaption></figcaption></figure></div>

   * Note: To import teams, you must configure table mappings for the team, its team members, and their relationships.
3. Click **Preview.**
4. From the preview screen, you will be able to view summary counts, warnings, entity tree, and raw table data that was found based on the the configuration details. Once you've confirmed the data looks correct, you can select **save**.

## How to connect Cortex entities to ServiceNow

To import entities from ServiceNow, follow the steps described below.

### Import entities from ServiceNow

See the documentation on:

* [Importing teams](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/teams#creating-a-team)
* [Importing services](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/add-services#creating-services)
* [Importing domains](/ingesting-data-into-cortex/entities-overview/entities/adding-entities/domains#creating-domains-and-a-hierarchy)
  * You can [enable automated import of domains](#enable-automated-import-of-domains-for-servicenow).
  * Domain relationships cannot be manually imported; these are automatically imported via the automatic import setting described below.

### Enable automated import of domains for ServiceNow

You must have the `Configure Settings` permission.

Enabling automated domain import ensures that your domain structure in Cortex stays up-to-date with your ServiceNow configuration.

1. In Cortex, go to the [ServiceNow settings page](https://app.getcortexapp.com/admin/integrations/servicenow).
2. Toggle the setting **on** to enable the automated import of any domains and domain relationships from ServiceNow.

<div align="left" data-full-width="false"><figure><img src="/files/YzmfJlmxLjwaQSEfFbSs" alt="" width="375"><figcaption></figcaption></figure></div>

The automatic sync runs daily at 2 p.m. UTC.

#### Manually sync domains

You must have the `Enable Relationship graph` permission.

To force a sync of newly-discovered domains:

1. Go to [**Tools > Relationship graphs**](https://app.getcortexapp.com/admin/graph) and select **Domains**.
2. Click the 3 dots icon in the upper right, then click **Sync**.\
   ![](/files/oRNSrQmLhBxgzXa8Mpii)

### Editing the entity descriptor

When an entity is connected to ServiceNow, the entity YAML will look like the following:

```yaml
x-cortex-servicenow:
  services:
  - tableName: cortex-services
    id: 1
```

#### Configuring your ServiceNow teams as owners

To import teams, [configure the table mappings](#step-2-configure-table-mappings) to pull teams, team members, and their relationships from ServiceNow. After doing so, [follow the steps to import them](#import-entities-from-servicenow).

When an entity is owned by a ServiceNow team, the YAML will look like the following:

```yaml
x-cortex-owners:
  - type: group
    name: My ServiceNow Team
    provider: SERVICE_NOW
    description: This is a description for this owner # optional
```

The value for `name` should be the name of the team as defined in ServiceNow (case-sensitive).

Learn more about ownership in [Defining ownership](/ingesting-data-into-cortex/entities-overview/entities/ownership).

## Using the ServiceNow integration

### Scorecards and CQL

With the ServiceNow integration, you can create Scorecard rules and write CQL queries based on ownership and team details.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>All ownership details</summary>

A special built-in type that supports a null check or a count check, used to enforce ownership of entities.

**Definition:** `ownership: Ownership | Null`

**Example**

An initial level in a security Scorecard might include a rule to ensure an entity has at least one team as an owner:

```
ownership.teams().length > 0
```

</details>

<details>

<summary>All owner details</summary>

List of owners, including team members and individual users, for each entity

**Definition:** `ownership.allOwners()`

**Example**

The Scorecard might include a rule to ensure that entity owners all have an email set:

```
ownership.allOwners().all((member) => member.email != null)
```

</details>

<details>

<summary>Team details</summary>

List of teams for each entity

**Definition:** `ownership.teams(): List<Team>`

**Example**

The Scorecard might include a rule to ensure that an entity owners all have a description and are not archived:

```
ownership.teams().all(team => team.description != null and team.isArchived == false)
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

### Workflows

After integrating, you can set up [Workflows](/streamline/workflows) to trigger actions in ServiceNow. See an example of this in Guides > Create ServiceNow incident.

### ServiceNow Incidents plugin

You can install a plugin that makes ServiceNow incidents more visible on your entity details pages:

<div align="left"><figure><img src="/files/GxUSWKW65HjoZyBKkNYl" alt=""><figcaption></figcaption></figure></div>

Learn more about installing the plugin in [Cortex Plugin Marketplace](/streamline/plugins/marketplace#cortex-built-plugins). You must have the `Edit Plugins` permission.

### Background sync

Cortex conducts a background sync of ServiceNow domains, domain relationships, and services every day at 2 p.m. UTC.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Slack

Configuring the integration for Slack

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

This article explains how to configure the integration for Slack. For instructions on using the AI Assistant, see [Using the integration for Slack](/ingesting-data-into-cortex/integrations/slack/using-the-integration-for-slack-ai-assistant).

## Why use the integration for Slack

Slack is where your team already communicates. Connecting it to Cortex brings your service ownership, standards, and alerts into the same place, so you spend less time switching tools and more time getting work done.

With the Slack integration, you can:

* **Ask questions, get answers**. The [Cortex AI Assistant](/get-started/cortex-ai-assistant) lets you query your Cortex environment in natural language, so you can find what you need without clicking through the UI. Ask the AI Assistant questions such as ***Which entities do I own?*** or ***Show me all critical services failing the Production Readiness Scorecard***.
* **Reach the right team faster**. Slack channels appear in the 'Owners' block on entity details pages, so you always know where to go when coordinating on a project or responding to an incident.
* **Stay on top of what matters.** Get notifications directly in Slack for Scorecard changes, upcoming Initiatives, weekly entity performance summaries, and more.
* **Enforce communication standards.** Build [Scorecards](/standardize/scorecards) that require projects to have a designated Slack channel, keeping ownership clear across your catalog.

## Configuring Slack

{% hint style="warning" %}
For on-premises Cortex instances, follow the manual configuration process. See [self-managed Slack](/self-managed/features/integrations/slack).
{% endhint %}

### Prerequisites

* Users with the `Configure Integrations` permissions can configure Slack.
* You must be an admin in your Slack account.
* The Slack account must not be linked to another Cortex tenant.

{% hint style="warning" %}
Slack channels are cached and refreshed every four (4) hours, so newly added or updated channels may not appear immediately in the UI or on an entity's details page.
{% endhint %}

### Step 1: Configuring Slack in Cortex

1. From the main sidebar, select **Integrations**.
2. Locate Slack, then click **Install**.
3. In the right panel, click **Add to Slack**.\
   The **Allow access** window opens.
4. From the **Workspace** drop-down menu, select your workspace.
5. Review the app permissions, then click **Allow**.\
   After signing in to Slack and granting permission for Cortex to access the Slack workspace, you are redirected to the Slack settings page in Cortex.
6. In the upper-right corner of the page, click **Test configuration** to test the connection.

### Step 2: Configuring Slack app settings

Follow the steps below to configure additional Slack settings.

1. From the main sidebar, select **Integrations**.
2. Locate Slack, then select **Settings**.
3. From the **Integration settings** tab, do any of the following:
   * Toggle on **Require Cortex account to use Cortex's Slack app** - Enable this setting if you want Cortex's Slack app to only work for users who have Cortex accounts.
   * Click **Notification settings** to configure notifications to be sent via Slack for your organization. See [Managing Slack notifications](#managing-slack-notifications) below for more information.
   * Click **Identity mappings** to map email addresses from your Slack workspace to email addresses of team members in Cortex, making sure the integration works as expected for users.\
     \
     **Tip**: Confirm that users' Slack accounts are connected from the [Onboarding management](https://app.getcortexapp.com/admin/onboard-management) tool or from the [identity mappings section in settings](https://app.getcortexapp.com/admin/settings/slack-mappings).

## Viewing Slack information in Cortex

Slack channels appear at the top of an entity's details page in a **Slack channels** block. They also appear in the **Owners** block in the entity's metadata sidebar.

Click a channel name to go directly to that channel in Slack.

<div data-full-width="false" data-with-frame="true"><figure><img src="/files/fu6zHJx0cTbSkoCBQh9g" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
Use Slack channel data to write CQL queries and build Scorecard rules. See [Creating Scorecard rules and writing CQL queries with the Slack integration](/ingesting-data-into-cortex/integrations/slack/using-the-integration-for-slack-ai-assistant#create-scorecard-rules).
{% endhint %}

## Managing Slack notifications

Slack notifications are controlled at two levels:

* **Workspace settings** - In Cortex, Admins (or users with the `Configure workspace notification settings` permission) can enable or disable Slack as a delivery channel for each notification type. This determines which notifications are available to send via Slack across the workspace.
* **Personal settings** - Individual users can then choose which of the available Slack notifications they want to receive in their own personal notification settings.

{% hint style="info" %}
If a notification type is disabled at the workspace level, users won't be able to opt into it in their personal settings.
{% endhint %}

**How notifications are routed**

Notifications are delivered by the integration and are routed based on their type:

* **User-based notifications** are sent as direct messages to the relevant user.
* **Team-based notifications** are sent to the Slack channel associated with a team.
* **Entity-based notifications** are sent to the Slack channel associated with an entity.

Notifications can be delivered to private Slack channels, but the Cortex AI Assistant must be a member of the channel for messages to come through.

Additionally, the AI Assistant sends user-based and team-based weekly reports. The user-based weekly report summarizes how their entities are tracking against Scorecards and Initiatives. The team-based report delivers the same summary for entities owned by that team.

See [Notifications](/configure/settings/notifications) for more information.


# Using the integration for Slack

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

This article explains how to use the integration for Slack with Cortex. For configuration instructions, see [Configuring the integration for Slack](/ingesting-data-into-cortex/integrations/slack).

{% hint style="info" %}
Cortex conducts a background sync of Slack identities every day at 10 a.m. UTC.
{% endhint %}

## Using the Cortex AI Assistant in Slack

{% hint style="info" %}
The Cortex AI Assistant requires the latest version of the Cortex Slack app. If you installed the app before February 2025, you'll need to update it before you can use the AI Assistant. Slack administrator permissions are required to perform the update.

To install, go to [Slack settings](https://app.getcortexapp.com/admin/integrations/slack) in Cortex. Delete the existing configuration and reinstall following the prompts.
{% endhint %}

After configuring the Slack integration, you can use commands to interact with the AI Assistant in your Slack workspace. The AI Assistant also powers notifications that are sent via Slack.

The AI Assistant is a Slack app called 'Cortex'. Use it with Slack in public or private channels, or via DM. Tag Cortex (type `@Cortex`) and ask a question.

You can also use the commands below in Slack to quickly query entity metadata and Scorecard scores. The `<tag>` refers to the entity's [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag).

<table><thead><tr><th width="272.28515625">Command</th><th>Result</th></tr></thead><tbody><tr><td><code>/cortex dependencies &#x3C;tag></code></td><td>List all incoming and outgoing first-level dependencies</td></tr><tr><td><code>/cortex deploys &#x3C;tag></code></td><td>List recent deploys</td></tr><tr><td><code>/cortex docs &#x3C;tag></code></td><td>List all <a href="/pages/5cEJd1jQZq1Shqjz7YAg">documentation links</a></td></tr><tr><td><code>/cortex domain &#x3C;tag></code></td><td>List domain information, such as owners, on-call, links, and timeline events</td></tr><tr><td><code>/cortex entity &#x3C;tag></code></td><td>List information for any entity, combining the behavior of <code>service</code>, <code>team</code>, <code>domain</code> and <code>resource</code></td></tr><tr><td><code>/cortex help &#x3C;tag></code></td><td>Display the full list of commands</td></tr><tr><td><code>/cortex links &#x3C;tag></code></td><td>List all <a href="/pages/5cEJd1jQZq1Shqjz7YAg">links</a></td></tr><tr><td><code>/cortex links [type] &#x3C;tag></code></td><td>List all links of a type parameter, such as metrics or openapi</td></tr><tr><td><code>/cortex logs &#x3C;tag></code></td><td>List all <a href="/pages/5cEJd1jQZq1Shqjz7YAg">logs links</a></td></tr><tr><td><code>/cortex oncall &#x3C;tag></code></td><td>Find current on-call info</td></tr><tr><td><code>/cortex owners &#x3C;tag></code></td><td>List all owners and their email addresses</td></tr><tr><td><code>/cortex resource &#x3C;tag></code></td><td>List resource information, such as owners, on-call, links, and timeline events</td></tr><tr><td><code>/cortex runbooks &#x3C;tag></code></td><td>List all <a href="/pages/5cEJd1jQZq1Shqjz7YAg">runbook links</a></td></tr><tr><td><code>/cortex scores &#x3C;tag></code></td><td>List all Scorecard scores</td></tr><tr><td><code>/cortex search &#x3C;tag></code></td><td>Query for entities using <a href="https://lucene.apache.org/core/2_9_4/queryparsersyntax.html">Lucene queries</a>.<br><br>For example:<br>- Search by tag with <code>key:value</code><br>- Use wildcards: <code>foo*</code>, <code>foo:bar*</code><br>- Search by group with <code>group:name</code></td></tr><tr><td><code>/cortex sentry &#x3C;tag></code></td><td>List recent Sentry issues</td></tr><tr><td><code>/cortex service &#x3C;tag></code></td><td>List service information, such as owners, on-call, links, and timeline events</td></tr><tr><td><code>/cortex team &#x3C;tag></code></td><td>List team information, such as owned entities, links, and timeline events</td></tr><tr><td><code>/cortex timeline &#x3C;tag></code></td><td>List recent timeline events</td></tr></tbody></table>

### Adding the AI Assistant to a private channel

To ensure you receive notifications in a private channel, make sure you have added it to that channel:

1. Open the Slack channel where you want to add the AI Assistant.
2. Type and enter `@Cortex`.\
   Slack prompts you to take action.
3. Click **Add them**.\
   The AI Assistant is added to the channel.

### AI Assistant notifications

The AI Assistant sends you notifications based on which notifications are configured for your workspace and based on your personal notification settings. See [Managing Slack notifications](/ingesting-data-into-cortex/integrations/slack#managing-slack-notifications) for more information.

## Connecting an entity to a Slack channel

Slack channels must be associated with entities in Cortex. Connect them in an [entity descriptor](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file) (for GitOps workflows) or through the Cortex UI. Slack channels can also be added as [external documentation links](/ingesting-data-into-cortex/entities-overview/entities/external-docs) on an entity, even without configuring the integration.

### Connecting via the Cortex UI

1. Navigate to an entity's details page.
2. In the upper-right corner, click **Configure entity**.
3. Select the **Slack channels** tab, then click **Add**.
4. In the side pane, configure the Slack channel details:
   * **Channel name** - Type in or select your Slack channel's name.
   * **Description** - Add a description to help others understand the purpose of the Slack channel.
   * **Notifications** - If enabled, you will receive notifications to this Slack channel.
5. At the bottom of the side pane, click **Add**.

### Connecting via an entity descriptor

#### **Editing the entity descriptor**

For any entity type, you can use the entity descriptor to define Slack channels (by name or ID) and toggle notifications on or off for each one. Defined channels are then accessible directly from the entity's page in Cortex.

#### **When to define by channel name vs. channel ID**

Defining by name is more easily recognizable to users when viewing the entity's YAML. However, if a Slack channel's name is likely to change, it's better to define by ID as it won't break the entity's Slack link in Cortex.

**Defining by channel names**

{% hint style="info" %}
It's recommended to register Slack channels by ID, rather than by name, as channel names may change over time.
{% endhint %}

```yaml
x-cortex-slack:
  channels:
  - name: team-engineering
    notificationsEnabled: true
    description: A description for this Slack channel.
```

| Field                  | Description                                         | Required |
| ---------------------- | --------------------------------------------------- | -------- |
| `name`                 | Slack channel name                                  | Yes      |
| `notificationsEnabled` | Boolean to enable or disable notifications in Slack | Yes      |
| `description`          | Description of the Slack channel                    | No       |

**Defining by channel IDs**

{% hint style="info" %}
It's recommended to register Slack channels by ID, rather than by name, as channel names may change over time.
{% endhint %}

```yaml
x-cortex-slack:
  channels:
  - id: ABCDEF123
    notificationsEnabled: true
    description: This is a description for this Slack channel
```

| Field                  | Description                                         | Required |
| ---------------------- | --------------------------------------------------- | -------- |
| `name`                 | Slack channel name                                  | Yes      |
| `notificationsEnabled` | Boolean to enable or disable notifications in Slack | Yes      |
| `description`          | Description of the Slack channel                    | No       |

**Connect channels to entities without configuring the integration for Slack**

You can connect Slack channels to entities without configuring the Slack integration. Note that this method only provides a link to Slack from the entity; it won't include any features of the Slack integration, such as ownership tracking, notifications, Slack Bot, and the ability to use CQL to query Slack data.

Use [Slack's redirect link](https://api.slack.com/reference/deep-linking#deep-linking-into-your-slack-app) format, `https://slack.com/app_redirect?channel={channel_name}`, to add the link to an entity YAML, under the `x-cortex-slack` block. Make sure to replace `channel_name` with your Slack channel's name.

```yaml
x-cortex-slack:
  channels:
  - name: https://slack.com/app_redirect?channel=channel_name
```

## Creating Scorecard rules and writing CQL queries with the Slack integration <a href="#create-scorecard-rules" id="create-scorecard-rules"></a>

See examples below.

<details>

<summary>Check if Slack channel is set</summary>

Checks if an entity has a registered Slack channel in its entity descriptor.

**Definition:** `slack (==/!=) null`

**Example**

For a Scorecard focused on onboarding entities, you can define a rule to make sure each entity has a registered Slack channel:

```
slack != null
```

Defining a rule to make sure a Slack channel is set is a good way to make sure that users can reach out to entity owners for more information or if an issue arises.

</details>

<details>

<summary>Number of Slack channels</summary>

Counts the number of Slack channels registered for a given entity.

**Definition:** `slack.channels().length`

**Example**

Similar to `slack != null`, you can use this expression to write a rule checking that entities are linked to a Slack channnel:

```
slack.channels().length > 0
```

This rule makes sure that there is at least one Slack channel set.

</details>

<details>

<summary>Total number of members across Slack channel</summary>

Counts the total number of members across all registered Slack channels.

**Definition:** `slack.numOfMembers()`

**Example**

You can use this expression in the Query Builder to find entities linked to empty Slack channels:

```
slack.numOfMembers() < 1
```

If an entity is linked to an empty Slack channel, it might indicate a gap in your notification process.

</details>

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer).

## Viewing Slack integration logs

{% hint style="info" %}
This feature is available in Cortex cloud.
{% endhint %}

Integration logs provide visibility into the activity between Cortex and Slack, making them a useful first stop when troubleshooting. You can use them to investigate failed notifications, confirm that webhooks are being delivered, and verify that recent configuration changes are working as expected.

1. From the main sidebar, select **Integrations**.
2. Locate Slack, then click **Settings**.
3. Select the **Logs** tab. Note that logs are retained for 7 days.

See [Troubleshooting with integration logs](https://docs.cortex.io/ingesting-data-into-cortex/integrations#troubleshooting-with-integration-logs) for more information.

## Privacy policy <a href="#privacy-policy" id="privacy-policy"></a>

Cortex retains basic Slack metadata like user IDs for the period necessary to fulfill the purposes outlined in our [Privacy Policy](https://www.cortex.io/legal/privacy-policy) unless a longer retention period is required or permitted by law, or where the Customer Agreement requires or permits specific retention or deletion periods.

To request to access, transfer, or delete data, you can reach out to the Cortex support team.


# Slack integration FAQ and troubleshooting

See common frequently asked questions and troubleshooting information below.

**Can users access information via the AI Assistant if they haven't logged in to our Cortex instance?**

Yes, this is possible, depending on the settings you configured for the AI Assistant in your workspace. To allow users to use the AI Assistant without logging in to Cortex, navigate to the [Slack integration settings page](https://app.getcortexapp.com/admin/settings/slack) in Cortex and toggle off **Require Cortex account to use Cortex's Slack app**.

**Can I disable some of the notifications I receive in Slack?**

You can adjust your personal notification settings, but note that [some types of notifications cannot be disabled](/configure/settings/notifications#notifications-that-cannot-be-disabled).

**Is the Slack integration required to add Slack channels to a team?**

No, the Slack integration is not required to add channels to Cortex teams. You can manually add any Slack channels without setting up the Slack integration [via the entity descriptor](/ingesting-data-into-cortex/integrations/slack/using-the-integration-for-slack-ai-assistant#connecting-via-an-entity-descriptor) or [via the API](/api/readme/teams) for a team’s metadata.

**Why isn't my Slack channel showing up after I've added it to an entity's YAML configuration?**

Slack channels are cached and refreshed every four (4) hours, so newly-added channels may not appear immediately in the UI.

**The AI Assistant isn't responding to my messages.**

Ensure '@Cortex' has been invited to the channel. The AI Assistant works in public and private channels, and via DMs. Make sure your slack identity is also mapped. See [Configuring identity mappings](/configure/settings/managing-users/identity-mapping).

**The AI Assistant lost context from earlier in the thread.**

Very long threads may exceed the conversation context window. If this happens, start a new thread and re-state the relevant context in your first message.

**Can I make changes to Cortex via the AI Assistant in Slack?**

No. The AI Assistant is read-only and only handles `GET` requests. It cannot modify or write data in your Cortex workspace. It can however, provide guidance and syntax on using our API or updating data to help you make any changes!

**Can I use the AI Assistant with Microsoft Teams?**

Currently, the Cortex AI Assistant is not compatible with Microsoft Teams.


# Snyk

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Snyk](https://snyk.io/) is a cybersecurity platform that scans for and surfaces vulnerabilities across your codebase.

Integrating Snyk with Cortex allows you to:

* [View vulnerabilities on entity pages in Cortex](#viewing-snyk-vulnerabilities-on-an-entity), quickly connecting issues to entities and their owners
  * Enhance the Snyk experience by aggregating issues into an entity's event timeline so they can be understood in the context of other events, like deploys and on-call incidents
* Use [Scorecards](#scorecards-and-cql) to measure entity quality based on Snyk data and drive quality improvements to your security practices

## How to configure Snyk with Cortex

### Prerequisites

Before getting started:

* Create a [Snyk API token](https://docs.snyk.io/snyk-api/authentication-for-api). The token will need the following read permissions:
  * `View Organization Reports`: Lists reporting issue counts.
  * `View Organization`: Allows Cortex to get a flattened list of all projects across all orgs.
  * `View Project History`: Allows Cortex to get project history.
  * `View Project`: Lists issues for a project.

### Configure the integration in Cortex

Once you've created an API token in Snyk, you can create a configuration from [Snyk settings](https://app.getcortexapp.com/admin/settings/snyk).

1. In Cortex, navigate to the [Snyk settings page](https://app.getcortexapp.com/admin/integrations/snyk):
   * Click **Integrations** from the main nav. Search for and select **Snyk**.
2. Click **Add configuration**.
3. Configure the integration form:
   * **API token**: Enter the API token you generated in Snyk.
   * **Region**: Enter the Snyk [region](https://docs.snyk.io/working-with-snyk/regional-hosting-and-data-residency#what-regions-are-available) where your data is hosted. The default region is USA.
4. Click **Save**.

After saving your configuration, you are redirected to the Snyk integration settings page in Cortex. On this page, you'll see a list of detected organizations pulled from Snyk, along with the unique Snyk ID and internal name associated with each organization.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Snyk projects

### Discovery

Cortex uses the Git repository as the "best guess" for the corresponding Snyk project since Snyk projects are connected to repositories. Cortex will search for all Snyk projects across all Snyk organizations and pull in projects associated with the same repository. For example, if the GitHub repo associated with your Snyk instance is `my-org/repo`, then the entities in Cortex should also be associated with `my-org/repo`.

### Editing the entity descriptor

You can define projects under the `x-cortex-snyk` block:

```yaml
x-cortex-snyk:
  projects:
    - organization: org-name
      projectId: 01234567-e65f-4b7b-a8b1-5b642894ec37
      source: CODE
```

| Field          | Description                                                                                                                                                                             | Required |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------: |
| `organization` | The `organizationID` or `organizationSlug` in Snyk                                                                                                                                      |   **✓**  |
| `projectId`    | The `projectID` defined in Snyk                                                                                                                                                         |   **✓**  |
| `source`       | [Enum field](https://en.wikipedia.org/wiki/Enumerated_type) that can be set to either `CODE` or `OPEN_SOURCE` to indicate the Snyk product type; defaults to `OPEN_SOURCE` when not set |          |

You can define `organization` with the organization ID or its slug in Snyk.

## Using the Snyk integration

### Viewing Snyk vulnerabilities on an entity

Once the Snyk integration is set up, you'll be able to find information about vulnerabilities for each entity linked to a discovered repo.

#### Entity page overview

On an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details) overview, see vulnerabilities listed under the **Code & security** block. Within this block, issues and vulnerabilities are grouped by severity: `Critical`, `High`, `Medium`, and `Low`. Click into any of these to open a list of all applicable issues and vulnerabilities.

#### Entity code & security sidebar

In an entity's sidebar, click **Code & security > Snyk** to view detected issues and vulnerabilities from Snyk, including the associated organization name and project name.

Because Snyk aggregates problems as "issues," data pulled in from Snyk will be listed as **issues**, while data pulled in from a Git source will be listed as **vulnerabilities**.

Vulnerabilities pulled from Git sources display the project name and a severity tag. Each issue pulled from Snyk displays the following information, when available:

* Title
* Issue ID (linked to the issue in Snyk)
* Publish date
* Severity tag
* Priority score tag

**Event timeline**

Issues from Snyk and vulnerabilities detected in Git appear in the entity's event timeline, which you can find from the **Events** link in the entity's sidebar. Issues and vulnerabilities display alongside other events, such as K8s changes, Git commits, and on-call incidents.

### Scorecards and CQL

With the Snyk integration, you can create Scorecard rules and write CQL queries based on Snyk projects.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Snyk project is set</summary>

Check if entity has a registered Snyk project in its entity descriptor. If no registration exists, but there is a Git repository registration, Cortex will try to automatically detect which corresponding Snyk project is associated with a given entity.

**Definition:** `snyk (==/!=) null`

**Example**

An initial level in a security Scorecard might include a rule to make sure entities are associated with Snyk project - without this, Cortex won't pick up data about issues from Snyk.

```
snyk != null
```

Setting a `snyk != null` rule can also serve as a secondary check to confirm an entity is synced properly with Snyk and is reporting frequently.

</details>

<details>

<summary>Number of Snyk issues</summary>

List all [aggregated issues](https://snyk.docs.apiary.io/#reference/projects/aggregated-project-issues/list-all-aggregated-issues) for a given entity's Snyk project.

* Project registration
* Aggregated issues for an entity's project
* Details about issues (when available)
  * CVSS score
  * Disclosure time
  * Exploit maturity
  * Issue ID
  * Language
  * Nearest fixed version
  * Original severity
  * Package name
  * Priority score
  * Publication time
  * Severity
  * Type
  * URL
  * Boolean characteristics:
    * Fixable or partially fixable
    * Ignored
    * Malicious
    * Patchable or patched
    * Pinnable
    * Upgradable

**Definition:** `snyk.issues().length`

**Example**

The Scorecard's top level might include a rule to ensure that entities have a low number of Snyk issues.

```
snyk.issues().length < 3
```

To indicate progress over time and incentivize further improvement, you could set an intermediate rule with a slightly higher count of Snyk issues.

```
snyk.issues().length < 5
```

If an entity has a Snyk project set and only one or two issues, it will achieve the highest level by these standards. An entity with a Snyk project set and three or four issues will achieve the next-highest level, while an entity with a Snyk project set and five or more issues will achieve the lowest level. Entities without a Snyk project will not achieve any level, regardless of how many issues they have.

You can also write more complex rules to set more specific standards. Instead of setting a rule for a moderate number of Snyk issues, you could check that entities have no outstanding critical issues.

```
snyk.numOfIssues(severity=["CRITICAL"], fixability=["FIXABLE"]) <= 0
```

</details>

{% hint style="warning" %}
Snyk does not currently support aggregated issues in regions outside of the U.S.A. Please use `.issues()` rather than `.numOfIssues()` if in a non-U.S.A. region.
{% endhint %}

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex fetches issues and vulnerabilities from Snyk and Git sources in real time. Depending on the volume of data, it may take additional time for the data to load on an entity page.

Projects from Snyk are synced every 6 hours.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# SonarQube

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[SonarQube](https://www.sonarsource.com/products/sonarqube/) is an open-source platform that empowers developers to write clean and safe code by continuously inspecting code quality and reviewing for bugs, vulnerabilities, and code duplication.

Integrating SonarQube with Cortex allows you to:

* Pull in code smells, bugs, code coverage, vulnerabilities, and custom metrics on [entity details pages](/ingesting-data-into-cortex/entities-overview/entities/details)
* Create [Scorecards](/standardize/scorecards) that track progress and drive alignment on projects involving your SonarQube projects

This integration is supported for both SonarQube Server and SonarQube Cloud.

## How to configure SonarQube with Cortex

### Self-hosted prerequisites

If you’re using a self-hosted instance of SonarQube, you’ll need to verify that your Cortex instance is able to reach the SonarQube instance.

If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your SonarQube instance.

### Configure the integration

There are two options for integrating SonarQube: the default configuration method and Cortex Axon Relay, a relay broker allows you to securely connect your on-premises SonarQube data.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

{% tabs %}
{% tab title="Default" %}
**Configure SonarQube with the default method**

**Prerequisites**

Before getting started, create a SonarQube user token:

* [SonarQube Server token instructions](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/managing-tokens/)
* [SonarQube Cloud token instructions](https://docs.sonarsource.com/sonarqube-cloud/managing-your-account/managing-tokens/)

**Configuration**

1. In Cortex, navigate to the [SonarQube settings page](https://app.getcortexapp.com/admin/integrations/sonarqube).
   * Click **Integrations** from the main nav. Search for and select **SonarQube**.
2. Click **Add configuration**.
3. Configure the SonarQube integration form:
   * **Account alias**: Enter the alias you will use to tie entity registrations to different configuration accounts.
   * **Token**: Enter your user token from SonarQube.
   * **SonarQube URL**: Enter the URL for your SonarQube instance.
     * For example, `https://sonarcloud.io` if you are on SonarQube Cloud, or `https://sonarqube.mycompany.com` if your organization has their own instance.
4. Click **Save**.
   {% endtab %}

{% tab title="Relay broker" %}
**Configure SonarQube with Cortex Axon Relay**

See [Internally hosted integrations](/ingesting-data-into-cortex/integrations/axon-relay) for instructions. Make sure to follow the SonarQube-specific instructions for the docker-compose.yml file.
{% endtab %}
{% endtabs %}

#### Integrate via custom webhook

If you’re unable to expose your SonarQube instance to be reachable by Cortex, you can set up a [custom integration webhook](/ingesting-data-into-cortex/integrations/webhook). To learn more about SonarQube webhooks, visit their [webhook documentation](https://docs.sonarqube.org/latest/project-administration/webhooks/).

## How to connect Cortex entities to SonarQube projects

### Discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) as the "best guess" for SonarQube component key. For example, if your Cortex tag is `my-entity`, then the corresponding component key in SonarQube should also be `my-entity`.

If your SonarQube component key doesn't cleanly match the Cortex tag, you can override this in the Cortex entity descriptor.

{% hint style="warning" %}
If you’re using build-system tooling to push analysis to SonarQube, the plugin (e.g. Gradle, Maven) may be automatically generating a project key that’s different from the repo name.
{% endhint %}

### Connect entities via YAML or the Cortex UI

{% tabs %}
{% tab title="Cortex UI" %}
**Connect SonarQube entities via the Cortex UI**

1. Navigate to an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details) in Cortex.
2. In the upper right corner, click **Configure entity**.

   <div align="left"><figure><img src="/files/fEmHBrIb2mtAqwGC1cAq" alt="In the upper right side of an entity, click &#x22;Configure entity.&#x22;"><figcaption></figcaption></figure></div>
3. Click the **Code quality** link in the sidebar. \\

   <div align="left"><figure><img src="/files/BzjB8qNjyWtMmjN5IVqL" alt="Click Code quality, then enter your SonarQube project details." width="563"><figcaption></figcaption></figure></div>
4. In the center of the page, configure the details for your SonarQube project:
   * **Alias**: If you have multiple configurations, select the one that this project is associated with.
   * **Project**: Enter the project's name.
5. Click **Save changes**.
   {% endtab %}

{% tab title="Entity YAML" %}
**Editing the entity descriptor**

When managing entities via the [YAML entity descriptor](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file), you can configure SonarQube projects under the `x-cortex-static-analysis` block:

```yaml
x-cortex-static-analysis:
  sonarqube:
    project: sonar-project-key
    alias: sonarqube-alias
```

| Field         | Description                                                                                      | Required |
| ------------- | ------------------------------------------------------------------------------------------------ | :------: |
| `project`     | Project key defined in Sonarqube                                                                 |   **✓**  |
| `alias`       | Alias for the configuration in Cortex (only needed if you have opted into multi-account support) |          |
| {% endtab %}  |                                                                                                  |          |
| {% endtabs %} |                                                                                                  |          |

{% hint style="warning" %}
Cortex only supports one SonarQube project per entity.
{% endhint %}

## Using the SonarQube integration

### View SonarQube data on entity pages

Once the integration is established, data from SonarQube will be available in the **Code & security** page in an [entity's sidebar,](/ingesting-data-into-cortex/entities-overview/entities/details#entity-details-sidebar) as well as under the Overview tab. You can pull in data on **code smells, bugs, code coverage, vulnerabilities, and any custom metrics** available through Sonar. You can read more about metric definitions in Sonar's [documentation](https://docs.sonarsource.com/sonarqube/latest/user-guide/metric-definitions/).

* Metrics
  * Complexity
  * Duplications
  * Issues
  * Maintainability
  * Quality gates
  * Reliability
  * Security
  * Size
  * Tests
* Code freshness
* Code coverage

### Scorecards and CQL

With the SonarQube integration, you can create Scorecard rules and write CQL queries based on SonarQube projects.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Analysis freshness</summary>

Duration since the last analysis was uploaded to SonarQube for a given project (with granularity of days).

**Definition:** `sonarqube.freshness()`

**Example**

For a Scorecard focused on operational readiness, you can use this expression to evaluate the freshness of static analysis metrics from SonarQube.

```
sonarqube.freshness() <= duration("P7D")
```

This rule checks that an analysis has been uploaded to SonarQube within the past week, which developers can use to make sure the metrics being pulled aren't stale.

This same rule would work in a security Scorecard - by making sure a SonarQube analysis has been uploaded within the last seven days, you make sure teams are monitoring for compliance to coding rules.

</details>

<details>

<summary>Metric</summary>

Query metrics generated by static analysis of your projects and sent to SonarQube:

* Alert status
* Bugs
* Code smells
* Coverage
* Duplicated lines
* Duplicated lines density
* Lines of code
* New blocker violations
* New bugs
* New code smells
* New coverage
* New security hotspots
* New violations
* Reliability rating
* Security hotspots
* Security rating
* Security review rating
* SQALE rating
* Vulnerabilities

**Definition:** `sonarqube.metric("<metric>")`

**Examples**

**Development maturity Scorecard**

**Code coverage**

For a Scorecard focused on development maturity, you can set a rule to make sure entities have greater than 80% code coverage.

```
sonarqube.metric("coverage") > 0.80
```

Developers can then immediately identify entities that are falling behind to make improvements to testing effectiveness. This Scorecard can also give users a more comprehensive sense of how well code is being tested, and where gaps exist.

This rule also serves as a secondary check that a given entity is hooked up to SonarQube and reporting frequently.

**Security Scorecard**

**Vulnerabilities**

You can also use the `sonarqube.metric("<metric>")` expression to write a rule for a security Scorecard, making sure production entities aren't deployed with a high number of security vulnerabilities. In an initial level of a Scorecard, you might write a rule to enforce 2 or less vulnerabilities:

```
sonarqube.metric("vulnerabilities") <= 2
```

Sonar recommends 0 vulnerabilities to achieve an A rating for Security, so a higher level in your Scorecard could enforce 0 vulnerabilities:

```
sonarqube.metric("vulnerabilities") = 0
```

**Code coverage**

In a security Scorecard, you could also use the following expression to evaluate code coverage. The [Sonar way quality gate](https://docs.sonarsource.com/sonarqube-server/quality-standards-administration/managing-quality-gates/introduction-to-quality-gates) requires code coverage to be at 80% or higher:

```
sonarqube.metric("coverage") > 80
```

Entities with low code coverage scores are more likely to be vulnerable to attack, so a lower threshold might make sense for certain security Scorecards.

**Security hotspots**

Rules focused on [security hotspots](https://docs.sonarsource.com/sonarqube/9.8/user-guide/security-hotspots/#what-is-a-security-hotspot) can also make sure entities are operating with minimal security issues. Hotspots highlight a security-sensitive piece of code where the overall application security may not be impacted; Sonar recommends reviewing 100% of hotspots. In the following rule example, you can aim for less than 2 hotspots that need review:

```
sonarqube.metric("security_hotspots") < 2
```

</details>

<details>

<summary>Project existence</summary>

SonarQube project exists for an entity.

**Definition:** `sonarqube != null`

**Example**

For a Scorecard focused on operational readiness, you can write a rule to make sure an entity has an associated SonarQube project.

```
sonarqube != null
```

Because having a SonarQube project set would be key for an entity to be evaluated via other SonarQube-related expressions, this rule would make sense in a Scorecard's initial level.

</details>

<details>

<summary>Issues</summary>

Query issues identified by static analysis of your projects and sent to SonarQube, including bugs, vulnerabilities, code smells, and more. If the statuses are not filled in, they will default to "OPEN" and "REOPENED" statuses to prevent fetching of resolved issues.

Sonar recommends targeting 0 new issues.

**Definition:** `sonarqube.issues("<types>", "<rules>", "<severities>", "<statuses>", "<lookback>"): List<SonarqubeIssue>`

**Example**

You can write a rule to check that an entity has fewer than 3 major java:S2142 bugs:

```
sonarqube.issues(types = ["bug"], rules = ["java:S2142"], severities = ["major"]).length <= 3
```

**Code smells**

In an initial level of a Scorecard, you could write a rule to check that an entity has fewer than 5 minor code smells:

```
sonarqube.issues(types = ["code_smell"], severities = ["minor"]).length < 5
```

In higher levels of the Scorecard, you could verify that the entity has 0 code smells, per Sonar's recommended best practices:

```
sonarqube.issues(types = ["code_smell"]).length < 1
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## FAQs and troubleshooting

#### **Does Cortex support SonarCloud?**

Yes. You can integrate with SonarCloud by following the same steps as integrating with SonarQube. In the URL field, use your `https://sonarcloud.io/` URL. You can also use multi-account support to add a self-hosted or SonarCloud instance by adding the URL for that instance during configuration.

#### **I’m seeing “Socket timed out when trying to connect to SonarQube” for all of my entities in Scorecards.**

This means that Cortex is unable to talk to your SonarQube instance. Make sure that your instance is running and accessible to Cortex.

#### **I’m using Gradle and I’ve verified that my project is in SonarQube, but Cortex is still showing me an error.**

Gradle automatically generates a project key which is equal to `[$:]$`. As a result, automatic discovery won’t work. You’ll need to override the project key in your Cortex [entity descriptor](#entity-descriptor).

#### **My project is in Sonar and Cortex is able to talk to SonarQube, but my score isn’t showing up.**

Try the following troubleshooting steps:

1. Make sure the project key in your YAML is exactly the same as the key in SonarQube.
2. Verify that the scores are in the “default branch” in SonarQube. If your scores are showing up in a `branch-a` in SonarQube, but your SonarQube default branch is `main`, Cortex will not be able to retrieve the scores.
3. Run the following curl command and verify there are metrics showing up in the response:

```bash
    curl -v -u : "https://[SONARQUBE HOST]/api/measures/
    component_tree?component=[SONARQUBE PROJECT KEY]&metricKeys=ncloc,coverage"
```

#### **What if I want to send custom data, but I don't have control over the integration touchpoint?**

If you don't have control of or access to the integration touchpoint (for example, if you're using a SonarQube notification webhook) you'll want to use the API to send custom data. You can find information on sending data to a custom data webhook [here](https://docs.cortex.io/api#tag/Custom-Data).

#### **Why might I see the SonarQube connection error `Component key not found`?**[**​**](https://docs.cortex.io/docs/reference/integrations/sonarqube#why-might-i-see-the-sonarqube-connection-error-component-key-not-found)

For SonarQube (and all integrations), Cortex will map the Cortex tag defined in the cortex.yaml for a given entity. For SonarQube specifically, the tag must **exactly match** the project ID in SonarQube. If these are not one-to-one, we recommend using the override detailed above to define the proper mapping for project ID and entity name.

#### **Why might I see the error `Sonarqube: Fail to request url` on my integration page or a `validity check failed` error while creating a Workflow?**[**​**](https://docs.cortex.io/docs/reference/integrations/sonarqube#why-might-i-see-the-error-sonarqube-fail-to-request-url-on-my-integration-page-or-a-validity-check-failed-error-while-creating-a-workflow)

This can happen if your external DNS certificate expired. Ensure that any certificates you're using are valid.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Splunk Observability Cloud (SignalFx)

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

Splunk Observability Cloud ([formerly known as SignalFx](https://www.splunk.com/en_us/newsroom/press-releases/2019/splunk-closes-acquisition-of-cloud-monitoring-leader-signalfx.html)) is a monitoring and analytics platform that allows customers to evaluate, visualize, automate, and alert on metrics.

Integrating Splunk Observability Cloud with Cortex allows you to:

* [View SLO information on entity pages](#viewing-slo-information-on-an-entity) in Cortex
* Create [Scorecards](#scorecards-and-cql) that include rules related to your Splunk Observability Cloud SLOs

## How to configure Splunk Observability Cloud with Cortex

### Prerequisites

Before getting started:

* Create an [access token](https://docs.splunk.com/observability/en/admin/authentication/authentication-tokens/org-tokens.html#create-an-access-token) in Splunk.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Splunk Observability settings page](https://app.getcortexapp.com/admin/integrations/splunk-observability):
   1. Click **Integrations** from the main nav. Search for and select **Splunk Observability**.
2. Click **Add configuration**.
3. Configure the integration form:
   * **Realm**: Enter your Splunk Observability realm.
     * You can find it in the URL for your instance, e.g., `https://app.{REALM}.signalfx.com/#/metrics`.
   * **Access token**: Enter the access token you generated in Splunk.
4. Click **Save**.

After saving your configuration, you are redirected to the Splunk Observability integration settings page in Cortex. In the upper right corner of the page, click **Test configuration** to ensure Splunk Observability was configured properly.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Splunk Observability SLOs

### Editing the entity descriptor

SLOs can be defined in the [entity descriptor](/ingesting-data-into-cortex/entities-overview/entities#defining-entities-via-yaml-file).

You can pull in data about SLOs and manage them in Cortex by defining relevant SLIs through queries, along with a threshold and a comparator. Cortex will pull data from Splunk Observability Cloud and roll up the query with a specified `rollup` function.

```yaml
x-cortex-slos:
  signalfx:
    - query: sf_metric:"jvm.memory.max" AND area:"nonheap"
      rollup: AVERAGE
      target: 5120000
      lookback: P1Y
      operation: "<="
```

| Field       | Description                                                                                                                                                                                                                                                                                           | Required |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------: |
| `query`     | [Elasticsearch query](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html) for your metric: Use `sf_metric` to filter by the given metric and add additional dimensions to narrow the searchQueries resulting in multiple datasets will be rolled up according to `rollup` |   **✓**  |
| `rollup`    | `SUM` or `AVERAGE`                                                                                                                                                                                                                                                                                    |   **✓**  |
| `target`    | Target number for the SLO                                                                                                                                                                                                                                                                             |   **✓**  |
| `lookback`  | [ISO-8601 duration](https://www.digi.com/resources/documentation/digidocs/90001488-13/reference/r_iso_8601_duration_format.htm) (`P[n]Y[n]M[n]DT[n]H[n]M[n]S`)                                                                                                                                        |   **✓**  |
| `operation` | `>`, `<`, `=`, `=`                                                                                                                                                                                                                                                                                    |   **✓**  |

## Using the Splunk Observability integration

### Viewing SLO information on an entity

When an SLO is defined in an entity's descriptor, SLO information appears in the **Monitoring** block on an [entity details page's](/ingesting-data-into-cortex/entities-overview/entities/details) overview.

**Monitoring**

* Click **Monitoring > Data overview** in the entity's sidebar to see the query, target, and current value for each SLO from any integrations you're pulling SLOs from. Each SLO also includes the period of time the SLO is being calculated for. For example, if the time listed is "7 days ago," then the SLO is looking at the time range starting 7 days ago to now.\\

  <div align="left"><figure><img src="/files/TX5CWyQphq5wQoGuSdot" alt="View SLOs in the entity sidebar under Monitoring > Data overview." width="563"><figcaption></figcaption></figure></div>
* Click **Monitoring > Splunk Observability** to view a graph of SLO performance over time.\\

  <div align="left"><figure><img src="/files/kmV2AxYU1wYfnCz1mery" alt="View a graph of SLO performance."><figcaption></figcaption></figure></div>

### Scorecards and CQL

With the Splunk Observability Cloud integration, you can create Scorecard rules and write CQL queries based on Splunk Observability Cloud SLOs.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>SLOs</summary>

SLOs associated with the entity via ID or tags. You can use this data to check whether an entity has SLOs associated with it, and if those SLOs are passing.

**Definition:** `slos: List<SLO>`

**Example**

In a Scorecard, you can use this expression to make sure an entity is passing its SLOs:

```
slos().all((slo) => slo.passing) == true
```

Use this expression to make sure latency Service Level Indicator (SLI) value is above 99.99%:

```
slos().filter((slo) => slo.name.matchesIn("latency") and slo.sliValue >= 0.9999).length > 0
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Splunk On-Call (VictorOps)

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

Splunk On-Call (formerly known as [VictorOps](https://www.splunk.com/en_us/about-splunk/acquisitions/splunk-on-call.html)) is an alert and on-call management platform.

Integrating Cortex with Splunk On-Call allows you to:

* Pull in on-call rotation data and escalation policies
  * The on-call user or team will appear in the **Current On-call** block on an entity's details page.
  * You can also view on-call information on an entity page in its side panel under **Integrations > On-call**.
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your on-call schedule

## How to configure Splunk On-Call with Cortex

### Prerequisites

Before getting started:

* Create a [Splunk On-Call API key](https://help.victorops.com/knowledge-base/api/).
  * Note: If the key is granted `Read-only` permissions, Cortex will only perform `GET` requests.
* Obtain your Splunk API ID.
  * In your Splunk On-Call portal, navigate to the **Integrations** page then click the **API** tab. Your API ID is displayed above your API keys.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Splunk On-call settings page](https://app.getcortexapp.com/admin/integrations/splunk-oncall):
   1. Click **Integrations** from the main nav. Search for and select **Splunk On-call**.
2. Click **Add configuration**.
3. Configure the VictorOps integration form:
   * **API ID**: Enter your API ID from Splunk On-Call.
   * **API key**: Enter your API key from Splunk On-Call.
   * **Organization slug**: Enter your Splunk On-Call organization slug.
     * This can be found at the end of the URL for your Splunk On-Call portal (e.g., `https://portal.victorops.com/dash/`)
   * **Client ID** and **Client secret**: Enter the client ID and secret associated with the application link you created in the previous steps.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Splunk On-Call

### Editing the entity descriptor

With the Splunk On-Call integration, you can tie on-call rotations to entities under the `x-cortex-oncall` block with your schedule metadata. You can use the team ID, or you can filter beyond the team ID and use the policy ID. Using the policy ID is helpful if your team has multiple policies available.

Team ID in entity descriptor:

```yaml
x-cortex-oncall:
  victorops:
    type: SCHEDULE
    id: team-abcd12345
```

Policy ID in entity descriptor:

```yaml
x-cortex-oncall:
  victorops:
    type: SCHEDULE
    id: team-abcd12345
    policyIds:
      - 12345
      - 56789
```

| Field  | Description                                     | Required |
| ------ | ----------------------------------------------- | :------: |
| `type` | Type of on-call data (in this case, `SCHEDULE`) |   **✓**  |
| `id`   | ID for the team assigned to the given schedule  |   **✓**  |

You can find the team ID in the Splunk On-Call portal on the teams page (e.g., `https://portal.victorops.com/dash/cortex-app#/team//users`).

## Using the Splunk On-Call integration

#### Entity pages

Once a Splunk On-Call schedule is defined in an entity descriptor, the user or team who is on call will appear in the **Current On-call** block on that [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details).

You can also find on-call information for a given entity on the **On-call & incidents** page in the entity's sidebar.

### Scorecards and CQL

With the Splunk On-Call integration, you can create Scorecard rules and write CQL queries based on Splunk On-Call schedules.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if on-call is set</summary>

Check if entity has a registered team.

**Definition:** `oncall (==/!=) null`

**Example**

For a Scorecard focused an production readiness, you can use this expression to make sure on-call is defined for entities:

```
oncall != null
```

This rule will pass if an entity has a service, schedule, or escalation policy set.

</details>

<details>

<summary>Number of escalations</summary>

Number of escalation tiers in escalation policy.

**Definition:** `oncall.numOfEscalations()`

**Example**

This expression could be used in a Scorecard focused on production readiness or service maturity:

```
oncall.numOfEscalations() >= 2
```

This rule checks that there are at least two tiers in an escalation policy for a given entity, so that if the first on-call does not ack, there is a backup.

</details>

<details>

<summary>On-call metadata</summary>

On-call metadata, including type, ID, and name.

**Definition:** `oncall.details()`

**Example**

You can use this expression in the Query builder to find all entities with an on-call rotation that includes a specific team. Let's say we want to find all entities that the "Sample Team" team is on-call for and the team's ID in Splunk On-Call is `sample-team1234`. Our query would then be:

```
oncall.details().id == "sample-team1234"
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Sumo Logic

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

## Overview

[Sumo Logic](https://www.sumologic.com/) is a cloud-based observability platform that provides log management and analytics. Integrate Sumo Logic with Cortex to drive insights into service-level objectives (SLOs).

## How to configure Sumo Logic with Cortex

### Prerequisites

Before getting started:

* [Generate an access key](https://help.sumologic.com/docs/api/getting-started/#authentication) in Sumo Logic.
* Determine your [assigned deployment](https://help.sumologic.com/docs/api/getting-started/#sumo-logic-endpoints-by-deployment-and-firewall-security) in Sumo Logic.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Sumo Logic settings page](https://app.getcortexapp.com/admin/integrations/sumologic):
   * Click **Integrations** from the main nav. Search for and select **Sumo Logic**.
2. Click **Add configuration**.
3. Configure the Sumo Logic integration form:
   * **Access ID**: Enter the access ID for Sumo Logic.
   * **Access key**: Enter the access key you generated in Sumo Logic.
   * **Deployment**: Enter your Sumo Logic deployment.
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

### Linking SLOs in Cortex

You can create and manage SLOs by listing SLO IDs in the entity descriptor:

```yaml
x-cortex-slos:
  sumologic:
    - id: 000000000001234
    - id: 000000000006789
```

## Using the Sumo Logic integration

#### Entity pages

When an SLO is defined in an entity's descriptor, you'll see an overview of SLO information in the **Monitoring** block on an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details) overview.

On the left side of an entity, click **Monitoring > Sumo Logic** to view the SLO query, target(s), current value for each SLO, a graph of SLO performance over time, and the period of time the SLO is being calculated for. For example, if the time listed is "7 days ago," then the SLO is looking at the time range starting 7 days ago to now.

### Scorecards and CQL

With the Sumo Logic integration, you can create Scorecard rules and write CQL queries based on Sumo Logic SLOs.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>SLOs</summary>

SLOs associated with the entity via ID or tags. You can use this data to check whether an entity has SLOs associated with it, and if those SLOs are passing.

**Definition:** `slos: List<SLO>`

**Example**

In a Scorecard, you can use this expression to make sure an entity is passing its SLOs:

```
slos().all((slo) => slo.passing) == true
```

Use this expression to make sure latency Service Level Indicator (SLI) value is above 99.99%:

```
slos().filter((slo) => slo.name.matchesIn("latency") and slo.sliValue >= 0.9999).length > 0
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Syntasso Kratix Enterprise (SKE)

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Syntasso Kratix Enterprise (SKE)](https://www.syntasso.io/) is an enterprise-grade platform orchestrator built on [Kratix](https://kratix.io/), an open-source framework for building internal developer platforms on Kubernetes. SKE enables platform teams to deliver self-service infrastructure and services through composable, API-driven abstractions called [Promises](https://docs.kratix.io/main/reference/promises/intro).

Integrating SKE with Cortex allows you to:

* Dynamically create [Workflows](/streamline/workflows) in Cortex that map to Kratix Promises, enabling developers to self-service Kubernetes resources
* Register and update entities in Cortex that represent Kubernetes resource definitions managed by SKE
* Provide a portal-driven experience where developers can request and manage platform capabilities without needing to learn YAML or kubectl

{% hint style="info" %}
This integration was built and is maintained by the Syntasso team. For setup and configuration, refer to the [SKE documentation](https://docs.kratix.io/ske).
{% endhint %}

## How to configure SKE with Cortex

### Prerequisites

Before getting started:

* You should have a working [SKE installation](https://docs.kratix.io/ske).
* You should have Promises configured in your SKE environment.
* You will need a [Cortex API key](/configure/settings/api-keys) to connect SKE to your Cortex workspace.

### Configure the integration

SKE connects to Cortex via the [Cortex API](https://docs.cortex.io/api). Configuration is managed on the SKE side — refer to the [SKE documentation](https://docs.kratix.io/ske) for detailed setup instructions.

Once configured, SKE will automatically create and manage [Workflows](/streamline/workflows) in Cortex based on the Promises defined in your platform.

## How the integration works

### Kratix Promises

Promises are the core abstraction in Kratix and SKE. A Promise defines a platform capability — such as a database, CI/CD pipeline, or Kubernetes cluster — as a self-service API. Promises encapsulate validation, provisioning, policy enforcement, and Day 2 lifecycle management into a single, governed contract between platform and development teams.

When SKE is integrated with Cortex, these Promises are surfaced as Workflows, allowing developers to request resources through the Cortex UI.

## Using the SKE integration

As platform adoption grows, a common challenge emerges: *What do we actually have, who owns it, and is it compliant?* The SKE integration with Cortex connects orchestration with organizational visibility, helping teams treat their platform as a product — one that is not only easy to consume but also measurable, governable, and continuously improved.

Once configured, SKE dynamically creates, adds, and updates Promises for Kubernetes resource definitions in Cortex, giving platform teams a unified portal experience for managing platform capabilities.

## Demo

See the video below for a demonstration of the Kratix integration with Cortex.

{% embed url="<https://www.youtube.com/watch?v=28v8X3mNnPU>" %}

## Learn more

* [Syntasso website](https://www.syntasso.io/)
* [Kratix documentation](https://docs.kratix.io/)
* [SKE documentation](https://docs.kratix.io/ske)

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don't have a Slack channel? Talk with your Customer Success Manager.


# Veracode

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Veracode](https://www.veracode.com/) is an automated security platform that identifies and remediates vulnerabilities in software applications. DAST, SAST, and SCA are supported.

Integrating Veracode with Cortex allows you to:

* [View Veracode findings on entity pages](#view-veracode-data-on-ntity-pages) in Cortex
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on Veracode vulnerability metrics

## How to configure Veracode with Cortex

### Prerequisite

Before getting started:

* Create an [API ID in Veracode](https://docs.veracode.com/r/c_api_credentials3).
  * If using XML, configure the ID with the following permissions:
    * `get Detailed report`
    * `get Build list`
    * `get sandbox list`
    * `get application list`
  * If using REST, configure the ID with the following permissions:
    * `get application`
    * `get findings`
* Create a [secret key in Veracode](https://docs.veracode.com/r/c_api_credentials3) with the following roles:
  * Creator or Security Lead
  * Reviewer or Security Lead
  * Results API

If you're using a self-hosted instance of Veracode, you'll need to verify that your Cortex instance is able to reach the Veracode instance.\
\
We route our requests through a static IP address. Reach out to support at <help@cortex.io> to receive details about our static IP. If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your Veracode instance.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Veracode settings page](https://app.getcortexapp.com/admin/integrations/veracode):
   1. Click **Integrations** from the main nav. Search for and select **Veracode**.
2. Click **Add configuration**.
3. Configure the Veracode integration form:
   * **Key ID**: Enter your Veracode API ID.
   * **Secret key**: Enter the secret key associated with your API ID.
   * **Region**: Enter your Veracode instance [region](https://docs.veracode.com/r/Region_Domains_for_Veracode_APIs).
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

### Advanced configuration

If you’re unable to expose your Veracode instance to be reachable by Cortex, you can set up a [custom integration webhook](/ingesting-data-into-cortex/entities-overview/entities/custom-data).

## How to connect Cortex entities to Veracode

### Editing the entity descriptor

You can set up the Veracode integration for an entity by specifying its Veracode application names or sandboxes in the `x-cortex-static-analysis` section of the entity descriptor. For example:

```yaml
x-cortex-static-analysis:
  veracode:
    applicationNames:
      - My Application
      - Second Application
    sandboxes:
      - applicationName: My Application
        sandboxName: My Sandbox
      - applicationName: Second Application
        sandboxName: Second Sandbox
```

The application and sandbox names must appear exactly as they are in Veracode.

## Using the Veracode integration

### View Veracode data on entity pages

On an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details) overview, Veracode findings will appear the **Code and Security** block.

When viewing an entity, click **Code & security > Veracode** to see the DAST findings count, SAST findings count, SCA findings count, and a list of findings that can be filtered by severity and source. The data syncs automatically every hour, or you can click **Sync findings** in the upper right side of the entity's Veracode page to trigger a sync.

### Scorecards and CQL

With the Veracode integration, you can create Scorecard rules and write CQL queries based on Veracode findings.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Veracode application is set</summary>

Check if entity has Veracode application or sandbox specified in its entity descriptor.

**Definition:** `veracode (==/!= null): Boolean`

**Example**

In a Scorecard, you can write a rule to verify that an entity has a Veracode application or sandbox specified:

```
veracode != null
```

</details>

<details>

<summary>Findings</summary>

List of findings, filterable on risk, source, and status.

**Definition:** `veracode.findings(): List`

**Example**

In a Scorecard, you can write a rule to verify that an entity has fewer than 10 Veracode findings from two of the sources:

```
veracode.findings(source = ["STATIC", "SCA"]).length < 10
```

You can write a rule to verify that an entity has fewer than 3 findings with a risk level of 0 or 2:

```
veracode.findings(risk = ["0", "2"]).length <= 3
```

You can write a rule to verify that an entity has fewer than 5 findings with a status of "OPEN":

```
veracode.findings().filter((f) => f.findingStatus.status == "OPEN").length < 5
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex conducts an entity sync for Veracode every hour.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Wiz

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Wiz](https://www.wiz.io/) is a security platform that allows teams to find and fix issues in their code. Cortex integrates with Wiz to bring cloud and container vulnerabilities into your catalog.

Integrating Wiz with Cortex allows you to:

* [Automatically map projects to entities](#match-entity-names-to-wiz-projects), eliminating the overhead of manually maintaining project-to-entity relationships
* [View Wiz issues directly on entity pages](#view-wiz-information-on-entity-pages) in Cortex
  * Leverage Wiz scanning capabilities earlier in the development lifecycle and enable visibility into security issues
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving Wiz projects and issues

## How to configure Wiz with Cortex

### Prerequisites

Before getting started:

* [Create a service account in Wiz](https://docs.wiz.io/docs/service-accounts-settings).
* Obtain your [data center and authentication provider from Wiz](https://docs.wiz.io/docs/using-the-wiz-api).
* If you have IP restrictions in place in Wiz, [add Cortex's public IPs to your allowlist](https://docs.wiz.io/docs/req-urls-ip-addr) to ensure that Cortex is allowed to make requests to Wiz.
  * Contact the Cortex Customer Engineering team for a list of IPs.

### Configure the integration in Cortex

1. In Cortex, navigate to the [Wiz integration settings page](https://app.getcortexapp.com/admin/integrations/wiz):
   1. Click **Integrations** from the main nav. Search for and select **Wiz**.
2. Click **Add configuration**.
3. Configure the Wiz integration form:
   * **Client ID** and **Client secret**: Enter your client ID and client secret from Wiz.
   * **Tenant data center**: Enter the data center from Wiz.
   * **Authentication provider**: Select your authentication provider. You can confirm the provider in Wiz under **User Settings > Tenant**.
4. Click **Save**.

If you see a "No address associated with hostname" error, verify that you have entered the correct authentication provider.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## How to connect Cortex entities to Wiz

### Match entity names to Wiz projects

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-service`) as the "best guess" for Wiz project. For example, if your entity name is "My Service" or your tag is `my-service`, then the corresponding project name in Wiz should also be My Service or `my-service`.

If your Wiz project names don’t cleanly match the Cortex entity name or tag, you can override this in the Cortex entity descriptor.

#### Considerations for mapping Wiz projects to entities

Expand the tile below to see how Cortex customers have modeled their data when mapping Wiz projects to entities.

<details>

<summary>Wiz project mapping best practices</summary>

**Domain-level auto-mapping**

Some customers organize their Cortex domain structure to match their Wiz projects, enabling auto-mapping across domains based on their name.

For example:

* **Cortex domain entity name**: Engineering project
  * **Entity tag**: `engineering-project`
* **Wiz project name**: Engineering project

**Auto-mapping across multiple integrations**

Some customers organize multiple integrations to use consistent names and tags across all of them.

For example:

* **Cortex domain entity name**: Engineering project
  * **Entity tag**: `engineering-project`
* **Wiz project name**: Engineering project
* **Jira project name**: engineering-project
  * When you [integrate Cortex with Jira](/ingesting-data-into-cortex/integrations/jira), Cortex will tie Jira tickets to entities by searching for any tickets where the `label`, `component`, or `project` field for the work item includes the Cortex tag.

**Service-level auto-mapping based on repo structure**

Some customers use a standardized repository naming convention that makes service-level auto-mapping simple and automated to the Wiz projects.

For example:

* **Repository name**: engineering/integrations/eng-repo
* **Cortex domain entity name**: Eng Repo
  * **Entity tag in Cortex**: eng-repo
* **Wiz project name**: eng-repo

</details>

### Editing the entity descriptor

Define the following block in your Cortex entity descriptor:

```yaml
x-cortex-wiz:
  projects:
    - projectId: 01234567-e65f-4b7b-a8b1-5b642894ec37
```

## Using the Wiz integration

### View Wiz information on entity pages

On an [entity details page](/ingesting-data-into-cortex/entities-overview/entities/details), you'll see Wiz issues, listed by risk level, under the **Code and Security** header.

In the entity's sidebar, click **Code & Security > Wiz** to view a list of Wiz issues including their severity, status, basic details, and a link to view the issue directly in Wiz:

<figure><img src="/files/ZppCR04DGHw5x72JrN3G" alt="View Wiz issues on the entity details page under Code &#x26; security."><figcaption></figcaption></figure>

### Scorecards and CQL

With the Wiz integration, you can create Scorecard rules and write CQL queries based on Wiz projects.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if Wiz project is set</summary>

Check if entity has a registered Wiz project in its entity descriptor.

**Definition:** `wiz (==/!=) null: Boolean`

**Example**

An initial level in a security Scorecard might include a rule to make sure entities are associated with Wiz project:

```
wiz != null
```

Setting a `wiz != null` rule can also serve as a secondary check to confirm an entity is synced properly with Wiz and is reporting frequently.

</details>

<details>

<summary>Wiz issues</summary>

List of Wiz issues, filterable on severity and status

**Definition:** `wiz.issues(): List`

**Example**

The Scorecard's top level might include a rule to ensure that entities have fewer than 3 issues in OPEN status:

```
wiz.issues(statuses = ["OPEN"]).length <= 3
```

You could set rule to verify an entity has less than 10 issues with a HIGH or CRITICAL severity:

```
wiz.issues(severity = ["CRITICAL", "HIGH"]).length < 10
```

You can write a rule to verify an entity has less than 25 issues:

```
wiz.issues().length < 25
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Workday

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[Workday](https://www.workday.com/) is cloud-based enterprise software that unifies finance and workforce management in a single platform. Integrate Workday with Cortex to manage teams and hierarchies, enforce ownership, and drive operational excellence.

## How to configure Workday with Cortex

### Step 1: Generate an ownership report in Workday

Depending on how you want to manage teams and the corresponding hierarchy, you can choose one of the following options:

* Manage teams based on Workday supervisory organizations
* Manage teams based on Workday teams

The required fields in the report differ depending on which option you choose. See the tabs below for instructions.

{% tabs %}
{% tab title="Supervisory orgs" %}
Your report will need the following fields:

* `email`: Email address for employee. Use the same address that employees will use to access Cortex.
* `employeeId`: Unique ID for each employee.
* `firstName`: Employee first name. This will be displayed in Cortex.
* `lastName`: Employee last name. This will be displayed in Cortex.
* `employeeRole` **(optional)**: Employee role. This will be displayed in Cortex.
* `employeeSupervisoryOrgId`: The ID for the supervisory organization that the employee is in. Cortex uses this field to group employees.
* `teamDisplayName`: A display name for individual teams based on the `employeeSupervisoryOrgId`; this should be the same across all employees who belong to the same supervisory org. This will become the Cortex team name and tag.
* `managerEmail`: Email address for the employee's manager. If Cortex detects an employee with the same email as the `managerEmail`, that employee will be added to the team with a "Manager" role.
* `teamSupervisoryOrgId`: The supervisory org ID for the team that the employee is part of. The organization registered in this field will become a "parent" in the team hierarchy, while the org registered in `employeeSupervisoryOrgId` will become a "child" in the hierarchy.
* `teamListKey` (for One Employee - Multiple Teams): Key for the list of teams associated with a given user.

{% hint style="warning" %}
Any changes to the `employeeSupervisoryOrgId` will result in the creation of a new team because this field is how Cortex identifies teams.
{% endhint %}
{% endtab %}

{% tab title="Workday teams" %}
Your report will need the following fields:

* `email`: Email address for employee. Use the same address that employees will use to access Cortex.
* `employeeId`: Unique ID for each employee.
* `firstName`: Employee first name. This will be displayed in Cortex.
* `lastName`: Employee last name. This will be displayed in Cortex.
* `employeeRole` **(optional)**: Employee role. This will be displayed in Cortex.
* `teamName`: Team name for employee. This field is what we use to group employees into teams in Cortex.
* `teamDisplayName` **(optional)**: Display name for the team. This will be used for the title and the tag for any teams imported from Workday at time of import. If not included, `teamName` will be used instead. This should be the same for all employees on the same team.
* `managerEmail`: Email address for the employee's manager. Cortex uses this field to create team hierarchies. If Cortex detects an employee with the same email as the `managerEmail`, that employee will be added to the team with a "Manager" role.
  * **Omit this field** if you **do not** want to auto-import teams and the corresponding hierarchy from Workday.

{% hint style="warning" %}
Any changes to the `teamName` will result in the creation of a new team because this field is how Cortex identifies teams.
{% endhint %}
{% endtab %}
{% endtabs %}

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

### Step 2: Configure the integration in Cortex

1. In Cortex, navigate to the [Workday settings page](https://app.getcortexapp.com/admin/integrations/workday):
   * Click **Integrations** from the main nav. Search for and select **Workday**.
2. Click **Add configuration**.
3. Configure the Workday integration form:
   * **Username**: Enter the username associated with the Workday account used to generate the ownership report.
   * **Password**: Enter the password for the Workday username.
   * **Ownership report URL**: Enter the URL for the ownership report you generated.
     * Provide the base report URL. Do not include query parameters in the URL. If necessary, Cortex will append `?format=json` when making requests.
4. Click **Save**.

### Step 3: Configure the report mappings

After saving the configuration, you can configure how you want the fields to map to different elements in Cortex. The options available in each dropdown menu will mirror the fields included when generating the ownership report.

**Note on field mapping availability**

When you first add or update a Workday report URL, Cortex runs a background sync job to fetch and cache the report's column structure. The field mapping drop-downs on the configuration page are populated from this cache.

If you open the configuration page immediately after adding or rotating credentials, the drop-downs may appear empty or validation errors like "Employee Id is required" may surface before the sync completes. If this occurs, wait a few minutes and refresh the page—the column options populate once the background sync has finished.

Cortex also runs a daily sync to keep the field cache up-to-date. If your Workday report structure changes, the latest mapping drop-downs are reflected within 24 hours.

1. Configure the mappings:
   * **Employee Attributes**: Map report fields that pertain to employees, including the following:
     * **Employee ID**
     * **Email**
     * **First Name**
     * **Last Name**
     * **Role (optional)**
       * Imports employees' roles and populates a badge that appears next to an employee's name.
     * **Manager Email**
       * When added, lists the corresponding manager for a given employee. The report should also include an entry for the manager to populate the field.
   * **Team Attributes**: Map report fields that pertain to employees' teams.
     * **Team type**: Select whether to map the fields using `One Employee - One Team` or `One Employee - Multiple Teams`.
       * The `One Employee - One Team` configuration is best if your report includes employees who belong to a single team. The `One Employee - Multiple Teams` configuration is recommended if employees have a list of teams they belong to. This is best if you are configuring the integration based on [supervisory orgs](#supervisory-organizations) and/or if users manage teams they belong to.
     * If using `One Employee - One Team`:
       * **Team ID**: Enter the team ID. New teams are imported based on this ID. If the identifier (i.e. `teamName`) changes, Cortex will create a new team.
       * **Team Name**: Enter a display name for the team in Cortex. Cortex will update this name if changes are detected in Workday.
     * If using `One Employee - Multiple Teams`:
       * **Team List Key**: Enter the list key for the list that contains teams you want imported into Cortex for a given employee entry. This requires the `teamListKey` field in the Workday report. The `teamListKey` should be a list of objects, where each object has at least `teamName` and `teamId` properties:
         * **Team ID**: Enter the team ID. New teams are imported based on this ID. If the identifier (i.e. `teamName`) changes, Cortex will create a new team.
         * **Team ID - Fallback**: Enter a fallback team for a user who does not have an associated `teamListKey`.
         * **Team Name**: Enter a display name for the team in Cortex. Cortex will update this name if changes are detected in Workday.
         * **Team Name - Fallback**: Enter a fallback team name for the fallback team ID defined above.
2. At the bottom of the screen, click **Save**.

#### **Configure the hierarchy fields for auto-importing Workday teams**

If you choose to [automatically import Workday teams](#automatic-import-of-teams), you must also configure the hierarchy fields mappings:

* **Field on parent team**: The value selected becomes a parent team for value selected in **Field on child team**.
* **Is List**: Toggle **on** when an entry for the parent field is a parent to multiple teams.
* **Field on child team**: The value selected is defined as child team.
* **Root Team IDs**: The ID for the team you expect to be at the top of the hierarchy.
  * If set, Cortex will use this to [break cycles](#limitations) that may be in the hierarchy.

Note that you must [enable the option to auto-import Workday teams](#automatic-import-of-teams) in order to import hierarchies.

## How to connect Cortex entities to Workday

### Discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) as the "best guess" for Workday team. For example, if your Cortex tag is `my-entity`, then the corresponding name in Workday should also be `my-entity`.

If your Workday teams don’t cleanly match the Cortex tag, you can override this in the Cortex entity descriptor.

Note: The team name is case-sensitive and should be exactly the same as in the report's `teamDisplayName` or `teamName` field.

### Automatic import of teams

You can choose to automatically import discovered teams and team relationships from Workday into Cortex. Before enabling auto import, make sure your Workday report includes the `managerEmail` field to ensure that team relationships are imported.

1. Navigate to [**Settings > Entities > Teams**](https://app.getcortexapp.com/admin/settings/entities/teams) in Cortex.
2. Under **Enabled identity providers**, make sure the box is checked next to **Workday**.
3. Under **Enable auto import of teams**, click the toggle next to **Auto import teams** to turn this setting on.

The next automatic import will occur when the background [entities sync runs](#background-sync) at 9 a.m. UTC.

{% hint style="info" %}
If an entity already exists with a tag that matches the tag of a Workday team that you are importing, Cortex automatically adds a `-team` suffix to the Workday team's [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag).

For example, if `payments` exists as a Cortex tag in Cortex, then you import a Payments team from Workday, Cortex will import the team's tag as `payments-team`.
{% endhint %}

#### Manually trigger team import

You can also manually trigger this sync:

1. Navigate to [**Catalogs > Teams**](https://app.getcortexapp.com/admin/catalogs/teams) in Cortex.
2. Click **Create team**.
3. In the upper left corner, click **Sync teams**.

### Entity descriptor

```yaml
x-cortex-owners:
  - type: group
    name: workday-team-tag
    provider: CORTEX
    description: This is a description for this owner.
```

| Field         | Description                                                                                                                                                         | Required |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------: |
| `type`        | Ownership type (in this case, `group`)                                                                                                                              |   **✓**  |
| `name`        | The [tag of the Cortex team entity](/ingesting-data-into-cortex/entities-overview/entities#unique-identifiers-for-entities) linked to the auto-created Workday team |   **✓**  |
| `provider`    | The source of the team (in this case, it was a Cortex-created team)                                                                                                 |   **✓**  |
| `description` | Description for the owner                                                                                                                                           |          |

## Using the Workday integration

#### Entity pages

Once the integration is set up, Cortex will automatically import and structure your team hierarchy. Any teams imported from Workday will appear with a description: **"Automatically created by Cortex"**.

On each team's details page, any team members Cortex detects will populate under the **Members** tab. If you included the "Role" field in your Workday report, members' roles will appear in a badge next to their names.

### Scorecards and CQL

<details>

<summary>All ownership details</summary>

A special built-in type that supports a null check or a count check, used to enforce ownership of entities.

**Definition:** `ownership: Ownership | Null`

**Example**

An initial level in a security Scorecard might include a rule to ensure an entity has at least one team as an owner:

```
ownership.teams().length > 0
```

</details>

<details>

<summary>All owner details</summary>

List of owners, including team members and individual users, for each entity

**Definition:** `ownership.allOwners()`

**Example**

The Scorecard might include a rule to ensure that entity owners all have an email set:

```
ownership.allOwners().all((member) => member.email != null)
```

</details>

<details>

<summary>Team details</summary>

List of teams for each entity

**Definition:** `ownership.teams(): List<Team>`

**Example**

The Scorecard might include a rule to ensure that an entity owners all have a description and are not archived:

```
ownership.teams().all(team => team.description != null and team.isArchived == false)
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Background sync

Cortex syncs teams from the report every day at 9 a.m. UTC.

You can sync teams manually at any time by clicking the **Sync teams for Workday** button from [Workday settings page](https://app.getcortexapp.com/admin/integrations/workday) in Cortex. Doing so will **not** auto-import teams.

## Limitations

Cortex does not support hierarchies with cycles. For example, let's say `Employee A` is on the platform team, `Employee B` is on the frontend team, and both report to `Manager C` on the engineering team. If `Manager C` reported to someone on the platform team, that would create a cycle between the platform and engineering teams.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# xMatters

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[xMatters](https://www.xmatters.com/) is an on-call management platform.

Integrating Cortex with xMatters allows you to:

* Pull in on-call rotation data and escalation policies
  * The on-call user or team will appear in the **Current On-call** block on an entity's details page.
  * You can also view on-call information on an entity page in its side panel under **Integrations > On-call**.
* Trigger xMatters incidents from Cortex
* Create [Scorecards](#scorecards-and-cql) that track progress and drive alignment on projects involving your xMatters services

## How to configure xMatters with Cortex

### Configure the integration in Cortex

1. In Cortex, navigate to the [xMatters settings page](https://app.getcortexapp.com/admin/integrations/xmatters):
   1. Click **Integrations** from the main nav. Search for and select **xMatters**.
2. Click **Add configuration**.
3. Configure the xMatters integration form:
   * **Username** and **Password**: Enter your xMatters username and password.
   * **Organization slug**: Enter the organization slug for your xMatters instance.
     * This can be found in the URL for your instance (e.g., `https://.xmatters.com`)
4. Click **Save**.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations#modifying-an-existing-integration-configuration).

## Trigger an incident

While viewing an entity in Cortex, you can trigger an incident in xMatters:

1. In Cortex, navigate to an entity. On the left side of an entity details page, click **On-call & incidents**.
2. In the upper right side of the entity's "On-call" page, click **Trigger incident**.
3. Configure the incident modal:
   * **Summary**: Enter a title for the incident.
   * **Description**: Enter a description of the incident.
   * **Severity**: Select a severity level.
4. At the bottom of the modal, click **Trigger incident**.
   * A confirmation screen will appear. In the confirmation, click the link to view the incident in xMatters.

## How to connect Cortex entities to xMatters

### Discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities#cortex-tag) (e.g. `my-entity`) as the "best guess" for xMatters group. For example, if your Cortex tag is `my-entity`, then the corresponding group in xMatters should also be `my-entity`.

If your xMatters group don’t cleanly match the Cortex tag, you can override this in the Cortex entity descriptor.

### Editing the entity descriptor

```yaml
x-cortex-oncall:
  xmatters:
    id: engineering_group
    type: SERVICE
```

| Field  | Description                   | Required |
| ------ | ----------------------------- | :------: |
| `id`   | Name of the group in xMatters |   **✓**  |
| `type` | `SERVICE`                     |   **✓**  |

## Using the xMatters integration

#### Entity pages

Once the integration with xMatters is configured, you'll be able to find the user or team on call in the **Current On-call** block on an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details).

You can find more detailed information from the xMatters integration in the entity sidebar under **On-call & incidents > xMatters**.

The schedule associated with a given entity will be hyperlinked in the **Escalation Policy** block and the group will be hyperlinked in the **Service** block.

Under the Escalations section, you'll find each level associated with the policy. Owners assigned to each level will also be hyperlinked to the user or team's on-call page in xMatters.

### Scorecards and CQL

With the xMatters integration, you can create Scorecard rules and write CQL queries based on xMatters services.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Check if on-call is set</summary>

Check if entity has a registered group.

**Definition:** `oncall (==/!=) null`

**Example**

For a Scorecard focused an production readiness, you can use this expression to make sure on-call is defined for entities:

```
oncall != null
```

This rule will pass if an entity has an on-call schedule set.

</details>

<details>

<summary>Number of escalations</summary>

Number of escalation tiers in escalation policy.

**Definition:** `oncall.numOfEscalations()`

**Example**

This expression could be used in a Scorecard focused on production readiness or service maturity. For example, you can check that there are at least two tiers in an escalation policy for a given entity, so that if the first on-call does not ack, there is a backup:

```
oncall.numOfEscalations() >= 2
```

While making sure an on-call policy set is a rule that would be defined in a Scorecard's first level, a rule focused on escalation tiers would make more sense in a higher level.

</details>

<details>

<summary>On-call metadata</summary>

On-call metadata, including type, ID, and name.

**Definition:** `oncall.details()`

**Example**

You can use this expression in the Query builder to find all entities with an on-call rotation associated with a given group. Let's say we want to find all entities that the "Sample team" is on-call for.

```
oncall.details().id.matches("Sample*") == true
```

Because the team/group name is registered in the `ID` field in the entity descriptor, we would use `.id` instead of `.name`.

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


# Scorecards

Use Scorecards to establish best practices, track migration, promote accountability among teams, enforce standardization across entities, or define maturity standards.

{% stepper %}
{% step %}
**Define**

First, you create a Scorecard to set rules and define standards.

Learn more: [**Create a Scorecard**](/standardize/scorecards/create).
{% endstep %}

{% step %}
**Assess**

Next, you review the Scorecard to assess where the teams and entities stand today, allowing you to identify areas for improvement.

Learn more: [**Review and evaluate a Scorecard**](/standardize/scorecards/evaluate).
{% endstep %}

{% step %}
**Take action**

Last, you take action: Prioritize what to fix, set deadlines with [Initiatives](/improve/initiatives), and continue your Scorecard practices to ensure ongoing improvement.

Learn more: [**Take action on a Scorecard**](/standardize/scorecards/evaluate#take-action-on-a-scorecard).
{% endstep %}
{% endstepper %}

<figure><img src="/files/Sn2XbHfbqvlSq0VINDWW" alt="A list of scorecards is displayed"><figcaption></figcaption></figure>

In a Scorecard, entities are scored against rules. Rules can reference entities' metadata within Cortex, and can pull data from third-party integrations. Use levels and points in Scorecards to gamify the process and encourage developers to make progress toward goals.

While Scorecards do encourage teams to standardize entities, they do not have deadlines attached; if you have a goal that is more urgent or has a specific deadline, you can create an [Initiative](/improve/initiatives) to promote progress by a certain date.

### Common Scorecard use cases

See [Scorecard examples](#scorecard-examples) for common use cases and to see how others are motivating their teams with Scorecards.

{% hint style="success" %}
Looking to dive deeper? Check out the [Cortex Academy course on Scorecards](https://academy.cortex.io/courses/understanding-scorecards), available to all Cortex customers and POVs.
{% endhint %}

## Scorecards overview video

In the video below, learn how Scorecards, [Initiatives](/improve/initiatives), and [Reports](/improve/reports) can be used together to drive business goals.

{% embed url="<https://www.youtube.com/watch?v=oIWbMlK7Qh4>" %}

## Creating, viewing, and editing Scorecards

### Creating Scorecards

You can configure Scorecards directly in the Cortex UI, without needing to manage them solely through code. This makes it easier to get started, iterate over time, and involve more teammates without requiring deep context. If you prefer a GitOps approach, that's supported as well. See [Scorecards as code](/standardize/scorecards/scorecards-as-code) for more information.

On this page, learn about viewing and editing Scorecards. For step by step instructions on creating Scorecards, see [Creating a Scorecard](/standardize/scorecards/create). To learn about evaluating a Scorecard and mitigating failed rules, see [Review and evaluate Scorecards](/standardize/scorecards/evaluate).

Expand the tiles below to learn about viewing and editing Scorecards.

<details>

<summary>View Scorecards list</summary>

**View Scorecards list**

Click [**Scorecards**](https://app.getcortexapp.com/admin/scorecards) in the main nav in Cortex.

All of your organization’s Scorecards are listed under **All**. Under **Mine**, you’ll find Scorecards you’ve created, as well as Scorecards that evaluate entities you own.

<div align="left"><figure><img src="/files/8N0lBv3uHyKAGhQlcjls" alt="At the top of the Scorecard list, there are tabs for All and Mine" width="293"><figcaption></figcaption></figure></div>

</details>

<details>

<summary>Edit a Scorecard</summary>

**Edit a Scorecard**

If you have not [disabled UI editing](/configure/gitops#step-1-disable-ui-editing), then you can edit a Scorecard in the Cortex UI. You can edit the name, description, levels, rules, draft status, filter criteria, and the entity's being evaluated by the Scorecard. You cannot edit a Scorecard's unique identifier.

You must have the `Edit Scorecard` permission.

To edit:

1. Navigate to the Scorecard in Cortex.
2. Click **Edit** in the upper right corner of the Scorecard page:\\

   <figure><img src="/files/XKVeszrYvCmM2A1nvuH1" alt="Click &#x22;Edit&#x22; in the upper right corner."><figcaption></figcaption></figure>
3. Make changes to your Scorecard, then at the bottom of the page, click **Save Scorecard**.

Any time you edit and save your Scorecard, Cortex will automatically begin reevaluating the relevant entities to reflect your changes.

</details>

### Configuring global Scorecard settings

Admins can configure settings and view Scorecard rule exemptions under **Settings > Scorecards**.

See [Scorecard settings](/configure/settings/scorecard) for more information.

## Troubleshooting and FAQ

Cortex offers a wide variety of out-of-the-box integrations compatible with Scorecard rules. Sometimes, a Scorecard may have multiple integration queries with different endpoints, each with its own rate limits. While we strive to manage these rate limits efficiently, please keep the following points in mind regarding rule failures and third-party integrations:

#### **Are errors logged in the UI?**

Yes, any errors will be displayed alongside the rule for the relevant entity in the UI.

#### **Are the rules related to the errors retried?**

If we encounter a rate limit error, we will retry the rule for most integrations. This process occurs up to five times with a backoff period between attempts. If the rule fails after five retries, the last recorded score will be used.

#### **How are scores affected by missing values due to API rate limiting?**

If all retries are still affected by rate limit errors, we will use the last known score for the rule. This also applies to 5xx errors from upstream APIs and any unexpected errors from the Cortex side. If a new rule fails without a previous score, the rule will fail and display a 429 error.


# Create a Scorecard

Use Scorecards to establish best practices, track migration, promote accountability among teams, enforce standardization across entities, or define maturity standards.

This page explains how to create a Scorecard from the Cortex UI. For instructions on creating Scorecards via GitOps, see [Scorecards as code](/standardize/scorecards/scorecards-as-code). You can also work with Scorecards via the [Cortex API](/api/readme/scorecards).

Learn about reviewing, evaluating, and taking action on failed rules in [Review and evaluate Scorecards](/standardize/scorecards/evaluate).

### Common Scorecard use cases

For information about common use cases and examples, see [Scorecard examples](#scorecard-examples).

{% hint style="success" %}
Looking to dive deeper? Check out the [Cortex Academy course on Scorecards](https://academy.cortex.io/courses/understanding-scorecards), available to all Cortex customers and POVs.
{% endhint %}

## How to create Scorecards

### Prerequisites

* To create a Scorecard, you must have the admin or manager role, or you must have a custom role that includes the permission `Edit Scorecards`.
* Scorecards evaluate entities, so before using Scorecards, make sure you have [entities in your catalogs](/ingesting-data-into-cortex/entities-overview/entities).
* Make sure you have set up any [integrations](/ingesting-data-into-cortex/integrations) you want to write rules against.

### Step 1: Configure the basic Scorecard fields

When you create a new Scorecard, you can choose from the following options:

* **Use a Scorecard template**
* **Start from scratch**

#### Option 1: Use a template

Cortex offers the following templates:

<details>

<summary>Scorecard templates</summary>

* Onboarding Scorecard
* Production Readiness
* AI Maturity
* Service Maturity
* Incident Preparedness
* Incident Response Performance
* Security Scorecard
* SOC 2 Compliance
* Vulnerability Management
* Secrets Management
* Eng Intelligence metrics
* DORA Operational Readiness
* Velocity Scorecard
* Ownership Verification
* Entity Verification
* Code Quality
* JavaScript Best Practices
* Minimum Postgres version for Aurora
* Minimum version for ElastiCache for Redis
* Minimum Lambda runtime versions
* Empty Scorecard with Gold/Silver/Bronze levels pre-configured

</details>

Expand the tile below to learn how to create a Scorecard from a template.

<details>

<summary>Create Scorecard from template</summary>

To create a Scorecard using a template:

1. On the Scorecards page in Cortex, click **Create Scorecard**.
2. Click **Scorecard template**.
3. Click the template you want to use, then at the bottom of the page, click **Continue**.
   * You will be redirected to a page that shows the default configuration for your Scorecard, including the integrations used by the Scorecard and the template's levels and rules. You will be able to modify the Scorecard on the next page.
4. Click **Continue** at the bottom of the Scorecard default configuration page.
5. Configure the basic fields for your Scorecard:
   * **Name**: Enter a descriptive name for your Scorecard.
   * **Identifier**: Enter a unique identifier for your Scorecard.
   * **Description**: Enter a description for your Scorecard.
   * **Evaluation window**: By default, Scorecards are evaluated every 4 hours. If you would like to evaluate Scorecards less frequently, you can override the evaluation window and enter a new number.
     * If a Scorecard is evaluating such a large number of entities that it cannot complete the evaluation in a 4-hour window without invoking rate limits, then a longer evaluation window is recommended.
     * You will also be able to [manually trigger an evaluation](#trigger-an-evaluation) when needed.
   * **Enable notifications**: Choose whether to enable notifications.
     * If notifications are enabled, users who own entities being evaluated by this Scorecard will receive alerts when there are relevant updates on the Scorecard and any corresponding initiatives.
     * **Notify when scores drop**: When enabled, you will be notified any time a score drops from the last time the Scorecard was evaluated.
   * **Enable exemptions**: Choose whether to enable Scorecard exemptions. If not set, it defaults to true.
     * See [Scorecard rule exemptions](/standardize/scorecards/rule-exemptions) for more information.
   * **Enable auto-approval exemptions**: Choose whether to enable auto-approving of Scorecard rule exemptions. If not set, it defaults to false.
   * **Enable user-specific notifications:** Add a field to allow your users to notify a specific user to approve a rule exemption request rather than all Admins.
     * If this field is enabled, Scorecard notifications will also be enabled automatically.
6. Select whether to apply this Scorecard to specific entities.
   * You can choose to include or exclude specific entity types.
   * Click **Advanced options** to see additional options for refining entity selection. You can include or exclude groups, and you can include a CQL expression to make your entity type selection.
     * When including a CQL expression, you will have the option to [test the query](/standardize/cql/run#step-2-test-the-query) against specified entities to verify that it works as expected.

If you want to use all of the default rules from the template, you can skip ahead to [Step 4: Save the Scorecard](#step-4-save-the-scorecard). If you want to add any rules or levels, follow the next steps.

</details>

#### Option 2: Start from scratch

<details>

<summary>Create Scorecard from scratch</summary>

1. On the Scorecards page in Cortex, click **Start from scratch**, then at the bottom of the page, click **Continue**.
2. Configure the basic fields for your Scorecard:
   * **Name**: Enter a descriptive name for your Scorecard.
   * **Identifier**: Enter a unique identifier for your Scorecard.
   * **Description**: Enter a description for your Scorecard.
   * **Evaluation window**: By default, Scorecards are evaluated every 4 hours. If you would like to evaluate Scorecards less frequently, you can override the evaluation window and enter a new number.
     * If a Scorecard is evaluating such a large number of entities that it cannot complete the evaluation in a 4-hour window without invoking rate limits, then a longer evaluation window is recommended.
   * **Enable notifications**: Choose whether to enable notifications.
     * If notifications are enabled, users who own entities being evaluated by this Scorecard will receive alerts when there are relevant updates on the Scorecard and any corresponding initiatives.
     * **Notify when scores drop**: When enabled, you will be notified any time a score drops from the last time the Scorecard was evaluated.
   * **Enable exemptions**: Choose whether allow users to request rule exemptions for evaluated entities. If not set, it defaults to enabled.
     * See [Scorecard rule exemptions](/standardize/scorecards/rule-exemptions) for more information.
   * **Enable auto-approval exemptions**: If exemptions are allowed, choose whether to enable auto-approval of Scorecard rule exemptions. If not set, it defaults to disabled.
3. Next to "Apply to specific entities," select whether to apply this Scorecard to specific entities:
   * **Selection type** and **Entity types**: Choose to include or exclude specific entity types. By default, the Scorecard will apply to all entities of the selected type(s).
   * Click **Advanced options** to see additional options for refining entity selection. You can include or exclude groups. For example, if you're creating a services-based Scorecard, you might choose to include those that belong in a "tier 1 services" group.
     * You can also include a CQL expression to make your entity type selection.\
       ![Configure whether the Scorecard applies to specific entities](/files/QZLILmMBk1mU1oKAYksC)

{% hint style="warning" %}
Advanced filtering only works with data that exist within Cortex, like entity groups, owners, and other custom data, but does not extend to third-party integrations.
{% endhint %}

See the next section for steps on choosing a scoring type and writing rules.

</details>

### Step 2: Add levels

When you [create a Scorecard](#create-a-scorecard), there are two options to set up your Scorecard's evaluation:

* **Level progression**
  * Establish progressive levels as you add rules to make it obvious which set of rules are the highest priority. Levels allow you to set up a gamified system to encourage developers to make progress toward goals and improve entities' performance.
    * Set your minimum requirements within the lowest level, and add increasingly higher priority rules to subsequent levels.
    * For an example demonstrating how levels work, see [Guides > Measure DORA progress](/guides/dora/scorecard#understanding-scorecard-levels).
* **Point-based rules**
  * Use points to assign weighted values to each rule you add to a Scorecard.

    * You can use point-based rules to set minimum requirements while also encouraging teams to add more metadata. For example, you could assign 1 point for adding a single runbook to an entity, and another point for adding additional runbooks:

    <div align="left"><figure><img src="/files/1VPFnm6WLkBccaP6kJh3" alt="One rule checks for a single runbook, and another rule checks for more than 1 runbook." width="375"><figcaption></figcaption></figure></div>

{% hint style="success" %}
If you choose to use only point-based rules in your Scorecard, then you do not need to create levels. You can skip to the next section: [Step 3: Create a rule](#step-3-create-a-rule).
{% endhint %}

#### Add a level

<details>

<summary>To add a level to a Scorecard:</summary>

1. While creating your Scorecard, in the "Define evaluation rules" section, click **Add level**.\
   ![Click Add level under the scoring type selection](/files/AVrR3n1hoVxDDoRkJO6Y)
2. In the modal, configure your level:
   * **Color**: Click the star icon to select a color for this level.
   * **Name**: Enter a name that represents this level.
     * You might choose to go with classic levels names, such as Bronze, Silver, and Gold, or you can choose something more unique to your organization.
     * Levels are designed to inspire progress on important goals, so consider level names that will motivate your team members.
   * **Description**: Enter a description for the level.
3. Click **Add level**.

You can add more levels to the Scorecard, or you can move on to the next step and add rules to each level.

</details>

#### **Reorder levels**

<details>

<summary>To reorder levels in a Scorecard:</summary>

You can reorder levels while creating or editing your Scorecard, if the Scorecard has more than one level. Click the arrows on the right side to reorder them:\
\
![Click the arrow on the right side of a level](/files/2TI3vlZKuEUQjMqSYlQn)

</details>

### Step 3: Create a rule

There are two methods for building a rule:

* Using the form builder
* Via the CQL editor

The form is the fastest option, as you can choose from pre-configured rules for each integration. The CQL editor is best when writing complex rules or accessing data from multiple sources.

Expand the tiles below for instructions on each option.

<details>

<summary>Use the form builder</summary>

1. While creating your Scorecard, in the "Define evaluation rules" section, click **Add rule**.
   * **Level progression scoring type**: Click **Add rule** within a level.\
     ![In a level titled "Level 1: Bronze" you can click "Add rule to Level 1 Bronze" in the lower left](/files/mmtv8bA4rHnjvMSVchJo)
     * When using the "Level progression" scoring type, we recommend including the most essential rules in the first level so developers know to prioritize them.
   * **Point-based rule scoring type**: Enable the toggle next to **Point-based rules**, then click **Add rule:**\
     ![Click Add rule under the scoring type selection](/files/yugEkrX2UviiaehmZiDK)
2. The rule creation modal defaults to the **Form** type, where you can choose a pre-configured rule based on configured integrations. \\
3. Configure the basic fields in the form:
   * **Integration**: Choose one of your configured integrations to apply this rule to.
   * **Rule**: Choose a rule.
   * The next fields vary depending on the type of rule you choose. For example, you may need to choose a boolean operation or set a file path.
   * **Rule name**: Enter a descriptive name. Names make it easier to understand the outcome of the rule without having to read the CQL expression.\
     ![Configure the form to create a rule](/files/O9IHrM0VZ7oj3Zxi1kOG)
4. Optionally configure the additional fields:
   * **Description**: Enter a description for the rule.
   * **Failure message**: Add links or instructions to tell users how they can remediate this rule if it's failing.
   * **Restrict rule to specific groups**: Select groups to include or exclude.
     * This option can be used when a group of entities should be evaluated by the Scorecard as a whole, but a specific rule in the Scorecard does not apply to that group.
     * See [Scorecard rule filters](/standardize/scorecards/scorecard-filters) for more information on configuring a filter.
   * **Points**: Enter how many points this rule is worth.
     * You can use points to signify each rule's importance. Rules worth more points are more critical than those with fewer points.
   * **Schedule evaluation start date**: If you want to schedule the evaluation of a rule to start on a specific date, schedule a start date here. When the field is blank, the rule will take effect immediately. If a start date is provided, the rule will take effect at the start of the specified day (UTC).
     * This is helpful when you want users to be aware of an upcoming rule, but you do not want to evaluate the Scorecard yet based on that rule.
     * Scheduled rules are visible to all users and will be included in the weekly team and user reports to help with socialization.
     * Users can choose to [receive notifications](/configure/settings/notifications) when a scheduled rule is added to a Scorecard evaluating an entity they own, and they can receive reminders before a scheduled rule impacting an owned entity goes into effect.
5. Click **Save rule**.

</details>

<details>

<summary>Use the CQL editor</summary>

1. While creating your Scorecard, in the "Define evaluation rules" section, click **Add rule**.
   * **Level progression scoring type**: Click **Add rule** within a level.\
     ![In a level titled "Level 1: Bronze" you can click "Add rule to Level 1 Bronze" in the lower left](/files/mmtv8bA4rHnjvMSVchJo)
     * When using the "Level progression" scoring type, we recommend including the most essential rules in the first level so developers know to prioritize them.
   * **Point-based rule scoring type**: Enable the toggle next to **Point-based rules**, then click **Add rule:**\
     ![Click Add rule under the scoring type selection](/files/yugEkrX2UviiaehmZiDK)
2. The rule creation modal defaults to the **Form** type, where you can choose a pre-configured rule based on configured integrations. To write a CQL expression instead, click **CQL:**\
   ![Choose Forms for the UI editor or CQL editor to write CQL rules](/files/2LnQhRehdf5sOlIwvwlq)
3. Configure the basic fields in the form:
   * **CQL expression**: Enter your CQL rule. On the right side of the modal, you can use CQL Explorer for help.
     * Note: If writing an expression that references a Jira issues, Cortex will not append new filter logic to your default JQL query. See [Adding filter logic to the default JQL query in a Scorecard](/ingesting-data-into-cortex/integrations/jira#adding-filter-logic-to-the-default-jql-query-in-a-scorecard) for more information.
   * **Rule name**: Enter a descriptive name. Names make it easier to understand the rule without having to read the CQL expression.
4. Optionally configure the additional fields:
   * **Description**: Enter a description for the rule.
   * **Failure message**: Add links or instructions to tell users how they can remediate this rule if it's failing.
   * **Restrict rule to specific groups**: Select groups to include or exclude.
     * This option can be used when a group of entities should be evaluated by the Scorecard as a whole, but a specific rule in the Scorecard does not apply to that group.
     * See [Scorecard rule filters](/standardize/scorecards/scorecard-filters) for more information on configuring a filter.
   * **Points**: Enter how many points this rule is worth.
     * You can use points to signify each rule's importance. Rules worth more points are more critical than those with fewer points.
   * **Schedule evaluation start date**: If you want to schedule the evaluation of a rule to start on a specific date, schedule a start date here. When the field is blank, the rule will take effect immediately. If a start date is provided, the rule will take effect at the start of the specified day (UTC).
     * This is helpful when you want users to be aware of an upcoming rule, but you do not want to evaluate the Scorecard yet based on that rule.
     * Scheduled rules are visible to all users and will be included in the weekly team and user reports to help with socialization.
     * Users can choose to [receive notifications](/configure/settings/notifications) when a scheduled rule is added to a Scorecard evaluating an entity they own, and they can receive reminders before a scheduled rule impacting an owned entity goes into effect.
5. Click **Save rule**.

</details>

You can repeat the steps above to continue adding rules to your Scorecard. You cannot duplicate a rule across levels, since developers will have already completed that task earlier. It is common, however, to have similar rules with different thresholds if you want developers to progress in stages. For example, a base level might require that the P50 latency for API requests is under 5 seconds, while a higher level may required that the same P50 is under 2 seconds.

### Step 4: Save the Scorecard

After you have finished adding levels and rules to your Scorecard, you are ready to save it as a draft or publish it.

1. Choose whether to keep your Scorecard in draft form, visible only to users with permission to configure Scorecards. To keep it in draft form, enable the toggle next to **Save as draft**.
   * If you choose to keep your Scorecard in draft status, it will not appear in reports or send notifications.
   * If you choose to publish your Scorecard, it will be visible to all users who have the `View Scorecards` permission. Notifications, if enabled, will be triggered.
2. Click **Create Scorecard**.

After you save the Scorecard, it will automatically evaluate all the entities that apply based on the rules you have configured, and you will be redirected to the Scorecard's page in Cortex.

## Next steps

After you have established Scorecards, there are different steps you can take to continuously improve:

* **Evaluate progress and take action**: Review the Scorecard via reports or by using Cortex MCP, identify trends, and figure out how to take action on the issues you've identified. Learn more in [Review and evaluate Scorecards](/standardize/scorecards/evaluate).
* **Target goals with Initiatives**: If you have failing rules, or if you have rules that are a higher priority, you can start using [Initiatives](/improve/initiatives) to drive progress across the organization. Initiatives allow you to prioritize specific rules within a Scorecard and set deadlines for team members to accomplish tasks. Learn more below.

### Create Initiative from Scorecard

[Initiatives](/improve/initiatives) allow you to prioritize specific rules and set deadlines, making sure your team members complete higher priority tasks on time. In a level-based Scorecard, you can set an Initiative that asks your team to complete all rules within a level by a certain date.

You can create an Initiative while viewing a Scorecard. Note that the Scorecard must be published - i.e., not in draft mode - in order to create an Initiative for it.

1. In the upper right corner, click **+Create initiative**.

   <figure><img src="/files/1RhDE1ppk2DU0xfdXPef" alt="Click &#x22;Create Initiative&#x22; in the upper right."><figcaption></figcaption></figure>
2. Configure the Initiative form.
   * For detailed instructions and examples, see the [Initiatives documentation](/improve/initiatives).

You can also create an Initiative while viewing reports for the Scorecard under its [**Reports** tab](/standardize/scorecards#reports).


# Review and evaluate Scorecards

Reviewing a Scorecard's evaluation gives you insight into patterns across teams or entities, and areas to prioritize for improvement.

<div align="left"><figure><img src="/files/kin9iHz2D9vDZn4ARv1C" alt="" width="375"><figcaption></figcaption></figure></div>

When an entity is failing a rule in a Scorecard, Cortex provides the information needed to review and remediate the issue efficiently. From there, teams can [take action on the failing rule](#take-action-on-a-scorecard). Resolving these failures not only improves the health and maturity of individual entities but also strengthens the overall reliability and compliance posture of the engineering organization.

## Scorecard evaluation

After you create and save a Scorecard, Cortex automatically evaluates the entities that the Scorecard applies to. How often the Scorecard is evaluated depends on the evaluation window you set when [configuring the basic fields of the Scorecard](#step-1-configure-the-basic-scorecard-fields).

Scorecard evaluations are also automatically initiated after Scorecard definition changes are processed via GitOps or other means.

When processing a Scorecard, the individual entity evaluations are spread out over the evaluation window you configured. The evaluation will finish before the next evaluation time is reached. Also note that CQL filters require their own independent evaluation, which can increase the time required to process the evaluation.

<details>

<summary>Manually trigger an evaluation</summary>

To manually trigger a Scorecard evaluation in the Cortex UI:

1. Navigate to the Scorecard's page in Cortex.
2. In the details panel on the right side of the page, click **Evaluate now**.\\

   <div align="left"><figure><img src="/files/MMWYtHa3gnpw6LHR6CbF" alt="Click &#x22;Evaluate now&#x22; in the right side of a Scorecard" width="563"><figcaption></figcaption></figure></div>

You can also kick off a [re-evaluation of a specific entity via the API](/api/readme/scorecards#post-api-v1-scorecards-tag-entity-entitytag-scores).

</details>

<details>

<summary>Cancel an evaluation</summary>

If a Scorecard is in the process of being evaluated, you can cancel it:

1. Navigate to the Scorecard's page in Cortex.
2. Click **Cancel** at the top of the page.\\

   <div align="left"><figure><img src="/files/5Bic3nzNQJ2pYv0NdQY5" alt="Click &#x22;Cancel&#x22; at the top of a Scorecard" width="563"><figcaption></figcaption></figure></div>

</details>

## Review a Scorecard

### Reviewing with Cortex MCP

Use Cortex MCP to quickly gain insights into the performance of your Scorecard. Ask questions in natural language, such as: *What is going on with my DORA Metrics Scorecard?* or *What steps can I take to improve my Eng Intelligence Scorecard scores?*

<details>

<summary>Example MCP Scorecard assessment</summary>

First, ask a question about a Scorecard. The MCP will display which Cortex APIs are being used to find an answer:

<figure><img src="/files/vUoNQwFGgEfXw7V2iEqa" alt="" width="563"><figcaption></figcaption></figure>

Next, it will provide context to help you improve your scores:

<figure><img src="/files/GDuwHvRvuO31Cvp7RBnY" alt="" width="521"><figcaption></figcaption></figure>

For this example, after listing out the priorities, it also gave us a list of quick wins and a suggestion for a systematic approach:

<figure><img src="/files/CS6fnxjyDJ4S8pUJXUOe" alt=""><figcaption></figcaption></figure>

</details>

From there, [take action](#take-action-on-a-scorecard) to remediate the issues and start meeting your defined standards.

Learn how to get started in [Cortex MCP](/get-started/mcp).

### Reviewing in the Cortex UI

<figure><img src="/files/JF3ITESu7dP7Z4xvSMG3" alt="View basic information on the Scorecard page"><figcaption></figcaption></figure>

When you navigate to a Scorecard's page in Cortex, see high-level information, including the median levels achieved per entity, percent of entities at the highest level, and percent of entities that haven't achieved a level. In the side panel, see basic information, including the total number of services being evaluated, scheduled rules, and the next evaluation time.

{% hint style="success" %}
When reviewing scores, identify where teams or entities have the most friction. Can you automate any processes via [Cortex Workflows](/streamline/workflows) to improve efficiency?
{% endhint %}

#### Share the Scorecard

Need to show progress to leadership? Click **Share** in the upper right corner. This copies a link to your clipboard, which you can share with anyone who has access to view this Scorecard in your workspace.

<figure><img src="/files/pf1Plh9p18ZVmEJB7ilV" alt="Click Share in the upper right."><figcaption></figcaption></figure>

#### Scorecard tabs

<div align="left"><figure><img src="/files/pru0s0vXFmwrRjX2wjvF" alt="" width="563"><figcaption></figcaption></figure></div>

On the Scorecard page, click through each of the tabs to learn more about the Scorecard:

<details>

<summary>Scores</summary>

Under **Scores**, view each entity that is being scored via this Scorecard, the entity's current overall level, and its points or number of rules passed per level.

Point-based Scorecards will display progress based on points, while level-based Scorecards will display the number of passing rules.

<figure><img src="/files/XT2uZn5AE5gogMOFBFbi" alt="The Scores tab shows scores and levels per entity."><figcaption></figcaption></figure>

For example, in the screen shot above, the first two entities achieved 50 points out of 50 possible points within the Bronze level of the Scorecard. They also each achieved 3 out of 3 possible points under the Silver level.

**View more about each entity**

Click an entity to open a side panel with more information:

<figure><img src="/files/EIXJi6EhtCEyGX0piUOv" alt="Click into an entity to view more information."><figcaption></figcaption></figure>

* Next to the entity name: A link to its entity details page
* At the top of the panel: The entity's current level, score, rank, percentile, and an overview of its rule progress
* Under the Rules tab: **A list of failing rules**, passing rules, and rules not evaluated yet
  * Review this section closely to understand areas you can [take action](#take-action-on-a-scorecard) on.
* Under the Exemptions tab: A list of exempted rules
* Under the Progress tab: A graph showing the entity's progress

**Filter and sort the scores list**

In the upper right corner of the list, click **Filter** to narrow the scope of the list. You can filter by domain, failing rules, groups, levels, owners, passing rules, and teams.

Click **Level** to select a different method to sort by, and choose whether to sort ascending or descending.

</details>

<details>

<summary>Overview</summary>

Under **Overview**, see which entity is the highest ranking, which entity is most at-risk, which rule is the most at-risk, the most improved entity, the entity with the worst drop, and the most-moved rule.

Under those metrics, see a graph displaying the progress of all rules. Click **All rules** above the graph to filter it by specific rules.

<figure><img src="/files/DV4kI67i7iFm5tHi8L8M" alt=""><figcaption></figcaption></figure>

By default, the **Trends and changes** blocks show data from the last month. Click **Last month** to select a different timeframe.

</details>

<details>

<summary>Rules</summary>

Under **Rules**, view all of the Scorecard's rules, per level. Expand a rule to see its CQL expression:

<figure><img src="/files/CwodZ8Kq40mXnN5JJOJH" alt=""><figcaption></figcaption></figure>

Note that if you did not set a name for a rule when you created it, it will display here as a CQL expression.

</details>

<details>

<summary>Reports</summary>

Under **Reports**, click to view a [Bird's Eye report](/improve/reports/birds-eye), [Progress report](/improve/reports/progress-report), or [Report card](/improve/reports/report-card).

<figure><img src="/files/Vyqhr5C7kU8OlVzKwUBq" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary>Exemptions</summary>

Under **Exemptions**, view a list of all rule exemptions that have been requested.

Each request includes its current status, the rule, an expiration date, the reason for the request, and the user who requested it.

**How exemptions affect scores**

When a rule is exempted, entities are not marked as passing or failing — the rule simply does not apply to those entities.

**Approving or denying exemptions**

You must have the the `Configure Scorecard Exemptions` permission to approve or deny exemptions.

To approve an exemption, click the checkmark icon. To deny an exemption, click the X icon:

<figure><img src="/files/mVD8Y1fdVqvsjHnjVyqO" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary>Initiatives</summary>

Under **Initiatives**, see all [Initiatives](/improve/initiatives) associated with the Scorecard.

<figure><img src="/files/tHjgk037E3oTk0t2nTIS" alt=""><figcaption></figcaption></figure>

</details>

## Take action on a Scorecard

A failed Scorecard rule gives teams actionable goals to make incremental improvements. Teams can focus on addressing the highest-impact failures first, track progress over time, and celebrate measurable wins, which reinforces a culture of improvement.

To remediate failed rules in a Scorecard:

1. Identify the failing rules

   * View the [Scores tab](#scores) on a Scorecard page to view a list of failing rules per entity. You can group by level to understand which entities have reached each level of the Scorecard.\
     In this example, the group of entities has met the Bronze level, but they are failing rules for Silver and Gold:

   <div align="left"><figure><img src="/files/fSJ3M8LhGbdfZ5CRQuY1" alt="" width="563"><figcaption></figcaption></figure></div>
2. Understand the cause

   * While viewing scores, click into an entity to open a side panel with more information about why rules are failing.
     * When [configuring a rule](/standardize/scorecards/create#step-3-create-a-rule), add a failure message to give clear steps on how you can remediate the rule if it fails.

   <div align="left"><figure><img src="/files/wTKV8oL0nZwFVgMd0CfL" alt="" width="533"><figcaption></figcaption></figure></div>

   * When linking to a Cortex workflow that can be run to remediate a failing rule, Cortex will automatically pass in the entity context to the entity selector (if applicable) on the workflow, so it will be selected by default. You can also set this up manually by appending either the Cortex entity tag or entity ID to the workflow URL from a Scorecard or plugin (e.g. [?entity={{context.entity.tag}}](https://app.getcortexapp.com/admin/workflows/3403?entity=%7B%7Bcontext.entity.tag%7D%7D)).

   <div align="left"><figure><img src="/files/KvGmVKZdrf8xLDYhLKsg" alt="When linking to a Workflow from a failed Scorecard rule, Cortex automatically selects the entity to use when running the Workflow." width="375"><figcaption></figcaption></figure></div>

   * [Request exemptions](/standardize/scorecards/rule-exemptions) if needed: In some cases, a rule may not apply to an entity. You can request to exempt an entity from the rule.
3. Track and prioritize issues
   * Use the [Engineering homepage](/streamline/homepage) to see a prioritized to-do list of failing rules across your owned entities and Scorecards. This helps you focus on addressing the most impactful issues first.

     <figure><img src="/files/2Nlp5xbEwmXjIPJupouN" alt=""><figcaption></figcaption></figure>
4. Remediate the issues
   * Address the underlying issue for each failed rule. This could involve adding missing documentation, configuring a monitoring integration, or any other action required to meet the rule's criteria.
     * In the example screen shot above, the rule failed because PagerDuty is not configured for the entity. You can follow the [instructions in Cortex's PagerDuty documentation](/ingesting-data-into-cortex/integrations/pagerduty#editing-the-entity-descriptor) to ensure that a PagerDuty service, schedule, or escalation policy is configured in the entity's descriptor YAML.\
       ![](/files/e21UGoYqxmRY0810Ctmz)
   * [Use Initiatives](/improve/initiatives) to set specific deadlines for higher priority tasks. Cortex will notify owners and team members when deadlines are approaching, helping ensure accountability.
5. Re-evaluate
   * The Scorecard will automatically [re-evaluate](#scorecard-evaluation) based on its schedule (or you can manually trigger an evaluation), allowing you to see the progress made and any remaining failing rules.\\

     <div align="left"><figure><img src="/files/o15xDVPMeP848HgCnUcd" alt=""><figcaption></figcaption></figure></div>

### Scalable remediation

When reviewing your Scorecard evaluations, you may notice trends — some teams struggling in specific areas, or some entities often not meeting standards.

In addition to remediating individual rules, you may want to think about how you can improve larger processes to drive excellence in a scalable way across your organization.

#### Use Workflows

Look for frequent challenging areas across teams. For example, is a team consistently failing to add runbooks to new services? Are there any failing rules relating to onboarding processes? When a standard is frequently being missed, it indicates an opportunity to automate that process with a [Cortex Workflow](/streamline/workflows).

You can use Workflows to streamline a set of repeatable steps, reducing human error and speeding efficiency for your teams.

{% columns %}
{% column %}

<div align="left"><figure><img src="/files/mnVBAmw8csTSrQ3VWC7K" alt="" width="344"><figcaption></figcaption></figure></div>
{% endcolumn %}

{% column %}
For example, you could create a Workflow to [streamline the process of Scaffolding new services](https://github.com/cortexapps/hippocampus/blob/master/standardize/scorecards/broken-reference/README.md), and include a User Input step that requires your users to ensure a runbook has been documented.
{% endcolumn %}
{% endcolumns %}

#### Analyze and troubleshoot trends

While viewing a group of entities that are failing rules, you can also look at organizational ways to support your teams or adjust processes.

**Team-specific patterns**

* Are all of the failing entities owned by a newer team?
  * Ensure that the newer team members are not feeling overwhelmed and have completed any necessary training.
  * Ensure that the team understands their scope and priorities.
  * Use [Eng Intelligence](/improve/eng-intelligence) dashboards and metrics visualizations to identify which parts of the software development lifecycle could be improved per team.
* Does one team own more entities than other teams?
  * Ensure the workload is spread fairly across your teams.
  * If one teams owns more due to tribal knowledge, it is a signal to ensure team members are documenting their knowledge. It could also help you identify areas to conduct training sessions.
  * When knowledge has been documented, make sure it is being [linked on related entities](/ingesting-data-into-cortex/entities-overview/entities/external-docs).
* Are some teams or services successful across several areas?
  * When viewing teams that are successful or entities that meet all of their standards, find ways to recognize these achievements publicly. Public recognition reinforces good practices and motivates your team.

**Service lifecycle patterns**

* Do older, legacy services have low scores, while newer ones align with standards?
  * This highlights modernization opportunities.
  * Learn about using Cortex for modernization in the [Cortex Academy course "Migrations and Modernizations,"](https://academy.cortex.io/courses/migrations-and-modernizations) available to all customers and POVs.

**Adoption over time**

* Are scores trending upward across the quarter in line with company initiatives?
  * Tracking Scorecard trends across time shows whether your internal initiatives (like a push for better test coverage) are effective.
  * To promote specific standards, you can [create an Initiative in Cortex based on a Scorecard](/standardize/scorecards/create#create-initiative-from-scorecard), which will encourage remediation by a deadline.


# Scorecard rule exemptions

In some instances, a Scorecard rule might not apply to an entity. For example, a rule may be linked to an [Initiative](/improve/initiatives) your team is actively working on and the failure notification may be irrelevant or noisy to developers. Or, in rarer cases, the Scorecard rule may not make sense for a given component, depending on the nature of that entity. In either case, rule exemptions allow you to filter out components that shouldn’t be evaluated by a specific rule.

With rule exemptions, entities are not marked as passing or failing — the rule simply does not apply to those entities. If you use point-based rules instead of levels, the exempted rule will not be included in the average for a component’s percentage score. If you use levels, an exempt rule allows an entity to progress to the next level.

Any user can [request a rule exemption](#how-to-request-a-rule-exemption), and Admins or users with the `Configure Scorecard exemptions` permission can [approve, deny or revoke a rule exemption](#how-to-approve-deny-or-revoke-a-rule-exemption). Users with the `View Scorecard exemptions` permission can view exemptions in Scorecards that have been requested by any user; without that permission, a user can only see their own requested exemptions.

See our knowledge base for [best practices on managing rule exemptions](https://support.getcortexapp.com/hc/en-us/articles/41443967173531-Best-practices-for-managing-Cortex-Scorecard-rule-exemptions).

## How to request a rule exemption

Any user can request an exemption. This can be done [via the API](/api/readme/scorecards#post-api-v1-scorecards-tag-entity-entitytag-exemption), or via the Cortex UI.

While viewing a Scorecard in the Cortex UI:

1. Click into an entity on which you want to request a rule exemption.
   * A side panel will open, showing each rule applied to that entity.
2. Next to the rule you want to request an exemption for, click the 3 dots icon, then click **Request exemption**.\\

   <figure><img src="/files/myzJDZEOSLMur7r2cidp" alt=""><figcaption></figcaption></figure>
3. In the Request rule exemption side panel, configure the details: Choose whether you want to request a permanent exemption or enter how many days you want to exempt the entity from this rule, and optionally include a reason.
   * We recommend including a reason when you submit an exemption request. Requests will be reviewed by admins, and a clear explanation will help them determine whether an exemption makes sense.
   * Learn more about [permanent vs. time-bound exemptions](#permanent-or-time-bound-exemptions) below.
4. Click **Submit request**.

If the Scorecard has the [**Enable auto-approval for exemptions** option](#auto-approval) enabled, then the exemption will automatically be approved.

If the Scorecard has user-specific notifications enabled, you'll need to select a user to notify of the rule exemption request. That user will be able to review, and approve or reject the request. If this field is not enabled, then all Admins will be notified of the request.

### Permanent or time-bound exemptions

You’ll use a permanent exemption when there’s no expectation an entity will pass a rule, whereas a time-bound exemption makes more sense when an entity is expected to be in compliance with a given rule by a certain time.

In many cases, a time-bound exemption will be related to an ongoing Initiative. For example, entities might be required to have an on-call rotation set up by the end of the quarter. In this case, a developer may request an exemption that ends a few weeks before the quarter concludes — this can serve as a backup reminder if on-call isn’t set up at that point, and in the meantime, the failing rule won’t add any noise to the developer’s workflow.

When the time period for a temporary exemption elapses, any entities that are not in compliance with the rule would display as failing, while those in compliance would display as passing.

## How to approve, deny, or revoke a rule exemption

To approve or deny rule exemptions, you must be an Admin, or you must have a custom role that contains the `Configure Scorecard exemptions` [permission](/configure/settings/managing-users/permissioning).

Admins are able to [view all rule exemptions in Settings](#view-all-exemptions), in addition to [seeing them in Scorecards](#view-exemptions-in-a-scorecard).

### Auto-approval

If your [Scorecard is configured](/standardize/scorecards#step-1-configure-the-basic-scorecard-fields) to enable auto-approval for exemptions, then you do not need to take any action to approve the exemption.

<div align="left"><figure><img src="/files/kHqusWhFDuKCNCdlbUIH" alt="In a Scorecard configuration, you can enable auto approval for exemptions." width="486"><figcaption></figcaption></figure></div>

After the user submits an exemption request, the exemption will appear in the Scorecard's **Exemptions** tab as `Exempt`, with the option to revoke the exemption appearing on the right side of the rule:

<figure><img src="/files/Mrt4hoEVMsFYBLutAOE8" alt="The rule displays with &#x22;Exempt&#x22; to show it has been approved for exemption."><figcaption></figcaption></figure>

Also note that if you are an admin user and you request an exemption, it will automatically approve.

### Manual approval

If you have [notifications enabled](/configure/settings/notifications#rule-exemption-request-users-only) for rule exemption requests, then you will receive a notification when a user requests an exemption. The notification includes the name of the requestor, the rule name and its Scorecard, the entity that the exemption applies to, the reason and timeframe provided by the requestor, and a direct link to approve or deny the request in Cortex.

If you do not have notifications enabled, you can [view the exemption requests in Cortex](#view-exempted-rules) (in Scorecard's Exemptions tab or under **Settings > Scorecards > Rule exemptions**) and then accept, reject, or revoke from there.

<figure><img src="/files/UITmBEwPcsvLZaPZ7pPi" alt=""><figcaption></figcaption></figure>

### API

You can [approve](/api/readme/scorecards#put-api-v1-scorecards-tag-entity-entitytag-exemption-approve), [deny](/api/readme/scorecards#put-api-v1-scorecards-tag-entity-entitytag-exemption-deny), or [revoke](/api/readme/scorecards#put-api-v1-scorecards-tag-entity-entitytag-exemption-revoke) a Scorecard rule exemption via the API.

## View exempted rules

Admins, or users with the `Configure Scorecard exemptions` [permission](/configure/settings/managing-users/permissioning), can view exemption requests, approve or deny the request, and revoke exemptions.

### View exemptions in a Scorecard

When viewing a Scorecard, click into the **Exemptions** tab to view requests for exemptions and rules that have already been exempted:

<div align="left"><figure><img src="/files/4xyOaHQJpEQbLy7z7bIL" alt="" width="479"><figcaption></figcaption></figure></div>

### View all exemptions

In [**Settings > Scorecards > Rule exemptions**](https://app.getcortexapp.com/admin/settings/scorecards/rule-exemptions), admins can view a list of all requested exemptions:

<figure><img src="/files/vCjWh66pHsLTk7kyW83a" alt=""><figcaption></figcaption></figure>


# Scorecard rule filters

Rule filters allow you to apply a Scorecard rule only to specific entities. It's helpful to use a rule filter when a rule doesn’t apply to every entity or every group.

You can apply a filter in the Cortex UI while building out your Scorecard rules, or you can write a custom CQL query to filter your rule.

## How to set up a Scorecard rule filter

1. When [setting up a rule for a Scorecard](/standardize/scorecards#step-3-create-a-rule), click and expand **Restrict rule to specific groups**.
2. Select the relevant groups to include or exclude.
   * Or, if you prefer to write a CQL query, click **Switch to CQL** under the group fields.\
     ![Choose groups to exclude or include](/files/2sjKmtJLEdt82F8BbXzg)
3. Click **Save rule**.

See the [Scorecard documentation](/standardize/scorecards) for instructions on the overall process of creating a Scorecard.

You can also edit an existing Scorecard to add a filter to a rule.

### Example Scorecard rule filter

For example, let's say that entities in the "billing" group don't need to have SLOs set up properly.

* In the rule "Has SLOs set up," apply a filter to exclude the "billing" group:\
  ![](/files/WruqhxQ6UrR5HTiw4Rvy)
* After saving the rule with the excluded group, view the Scorecard. Any entities in the "billing" group will not be scored against the "Has SLOs set up" rule. The rule will not appear as a passing or a failing rule; it will not be included at all.

#### View the filter on the Scorecard home page

Once a rule filter has been applied, you can still see it on a Scorecard’s home page. Navigate to the **Rules** tab and expand the rule to confirm it has been exempted.




---

[Next Page](/llms-full.txt/1)

