How to export your data from Cortex before the contract ends
A renewal, a licence change or a residency requirement can force you to get your catalog out of Cortex on a fixed timeline. The documented route is the REST API: GET /api/v1/catalog lists catalog entities, GET /api/v1/catalog/descriptors returns their descriptors, and GET /api/v1/catalog/{tagOrId} fetches a single entity. That covers the entity catalog and its descriptors, but scorecard results, historical states and tenant configuration may need separate handling, and no other export path is documented in the sources we reviewed. Start by listing what your teams actually depend on: entities, owners, scorecard rules, initiatives and integrations with other tools.
Descriptors are the most portable part of the export. Cortex entity descriptors use an OpenAPI-based x-cortex format available in YAML and JSON, so pull them in both formats where possible and keep the raw responses as an archive. Confirm with your Cortex account team which fields in the descriptor are complete and which are computed, and whether the API token you hold can read every entity type and every team. Run a test export against a sample of services with known owners and compare the counts with what the Cortex interface shows, so gaps surface before the deadline rather than at cutover.
Scorecard history, check results and audit trails are the items most likely to be missing from the API response, so ask the vendor in writing whether they can be exported, in what format, and under what retention rules. Also confirm how long your tenant stays readable after the contract ends. Record the answers in your exit file, because the migration plan depends on them. For the translation step into Backstage, see Backstage catalog descriptor format, which defines the target catalog-info.yaml structure.
What you can export from Cortex and how
This table maps each kind of Cortex data to its documented REST endpoint or descriptor format, and flags the limits you must confirm before a full export. Use it to plan which calls you script and which details to ask Cortex about before you start the cutover.
| Data type | Documented access | What to confirm before export |
|---|---|---|
| Catalog entities (list) | GET /api/v1/catalog | Pagination parameters, page size and the total entity count you can expect |
| Catalog search results | GET /api/v1/catalog/search | Query syntax for filtering by type, group or tag, and whether results match a full export |
| Descriptors | GET /api/v1/catalog/descriptors | Whether descriptors come back for every entity type and in both YAML and JSON |
| Single entity lookup | GET /api/v1/catalog/{tagOrId} | Whether lookups accept the entity tag as well as the internal ID, and how to handle deleted entities |
| Descriptor format | x-cortex format in YAML or JSON, OpenAPI-based | Which fields your team uses, such as owners, relationships and custom properties, and how each maps to Backstage |
| API rate limits and authentication | Token-based access to the REST API | Request rate limits, token scope and expiry, and any restrictions for bulk reads on your plan |
| Scorecards and initiatives | Not covered by the catalog endpoints listed here | Whether scorecard results can be exported and in what form, so you can plan a separate rebuild |
What does not come out through the documented API
The documented REST API covers catalog entities and descriptors, but several things a team relies on day to day sit outside it. Scorecard history, initiatives, membership and integration configuration each need a separate decision before cutover, and the cheapest route differs for each. Confirm every gap with Cortex in writing before you plan around it.
Scorecard history and scores
The entity endpoints return the entity and its descriptor, not the time series of scorecard results that shows how each service's score moved. Teams often need that trend to prove progress on engineering standards after cutover. Rebuild the current state from the entity data and the checks you define in Backstage, and record a dated snapshot of scores from Cortex before you switch off access. Ask Cortex whether historical scorecard data can be exported in bulk.
Initiatives and their progress
Initiatives, the campaigns that track work across many services, are not part of the descriptor format covered by the catalog endpoints. Their owners, due dates and per-service status would be lost if nobody records them. Export the initiative list and each service's status from the Cortex interface or a written request to Cortex, then store it as a spreadsheet or a Markdown file in a repository the team controls.
Users, teams and membership
Ownership in Cortex depends on which users belong to which teams, and those memberships are managed in your identity provider or in Cortex itself. The catalog descriptors reference owners, but the membership graph behind them may not be fully returned by the documented endpoints. Export the team roster from your identity provider, map each Group and User entity to it, and confirm that every Component has an owner that resolves to a Group in Backstage before you cut over.
Integration and webhook configuration
Connections to GitHub, GitLab, PagerDuty, Slack and similar tools are configured inside Cortex and are not descriptors, so the API will not return them. Without a written record, the sources that feed ownership and scorecard data will be silently missing after migration. Document each connector, its scope, its token owner and its sync schedule, then recreate them with Backstage's own integrations and plugins. Rotate credentials as part of the cutover.
Custom fields and rules
Custom properties and the rules that drive them can shape how an entity is classified, yet the mapping from those settings to catalog-info.yaml fields is not automatic. Review each custom field used in your descriptors and decide whether it becomes an annotation, a label or a Tech Insights check. Where a rule cannot be expressed in the documented format, ask Cortex for the rule definition in writing and keep a copy for audit.
Audit logs and access history
Who changed an entity, when a score was overridden and who accessed the portal are typically kept in the vendor's platform rather than in descriptors. Auditors and security teams may still ask for this history after you leave Cortex. Ask Cortex in writing what audit data is retained, in what form and for how long, and export it before your access ends. Store the export under your own retention policy.
How the x-cortex descriptor format maps to catalog-info.yaml
The conversion works best when you decide the target Backstage kind for each Cortex entity type before you touch any files. Cortex describes entities with an OpenAPI-based x-cortex structure that can be exported in YAML or JSON, and Backstage expects a catalog-info file per entity with a kind drawn from Component, API, Resource, System, Domain, Group, User, Template or Location. Start by listing every entity type present in your export, then map each to one Backstage kind in a shared document that engineering and platform owners sign off. Confirm the exact field names in your export against the Cortex documentation, because the names are the source of truth for your script.
Some mappings are close to one-to-one. Services and other deployable units usually map to Component, and groups and people map to Group and User, with ownership expressed as references such as group:default/payments-team in the spec.owner field. API entities are the clearest case: Backstage API entities can carry OpenAPI definitions, so the specification your Cortex export references can be carried over rather than retyped. The decisions sit elsewhere. Cortex concepts such as scorecard results, initiatives and custom metadata have no direct Backstage field, so you must choose between annotations, labels, a catalog extension, or leaving them in the archive. Systems and domains also need a rule for which parent each component belongs to.
Validate the mapping on a small sample before the full export. Convert five or six entities that cover each kind, load them into a local Backstage instance, and check that owners resolve, relationships render and API definitions display. Compare the Backstage entity count with the Cortex count for the same scope and record every field you dropped or moved, with a named owner for each decision. Review the Backstage descriptor format documentation while you write the validation checks, since it defines which fields each kind requires.
The sequence for a complete export and verification
This sequence moves Cortex catalog data into a verified Backstage catalog in a fixed order, so every entity is accounted for before anything reaches production. Each step produces an artifact you can check, and the final reconciliation decides whether cutover can proceed.
Inventory every catalog entity
Start by listing the full set of entities with GET /api/v1/catalog, which the Cortex REST API documents for listing catalog entities. Have the platform owner run this with a read-only API token and save the response unchanged, along with the date and the Cortex tenant name. Record the total count and the entity types you see, such as services, APIs and teams. This inventory is your baseline. Nothing is considered migrated until it matches this list, so do not edit or filter the response at this stage. Done means you have a timestamped, complete list you can hand to the reconciliation step later.
Pull descriptors for every entity
Use GET /api/v1/catalog/descriptors to retrieve the entity descriptors in the x-cortex format, which Cortex documents in both YAML and JSON. Run this step against the same tenant and token as the inventory so the two sets can be compared. Confirm with your Cortex account team which descriptor format and version your tenant returns, since descriptor fields are the main input to the conversion. Done means you have one descriptor file or payload per entity, and the count of descriptors matches the inventory or any difference is explained.
Fetch individual entities for detail
For each entity in the inventory, call GET /api/v1/catalog/{tagOrId} to fetch its full record. The descriptor pull can omit fields that the single-entity call returns, such as current ownership details and relationships, so this step fills those gaps. Script the loop, keep the identifier used for each call, and log any entity that returns an error or empty body. Done means every inventory entry has a matching single-entity response, and the failures are listed with their identifiers for follow-up.
Store the raw output unchanged
Write all three result sets to version-controlled or write-once storage exactly as the API returned them: the inventory listing, the descriptors and the individual entity responses. Keep the token and any personal data out of the files, and restrict access to the platform team. Create a manifest with file names, hashes and counts so the raw data can be proven later. Done means the raw export can be re-read without calling Cortex again, which matters if the tenant is changed or the subscription ends during the migration.
Convert descriptors into catalog-info files
Translate each x-cortex entity into a Backstage catalog-info.yaml descriptor using the kinds Backstage documents, such as Component, API, System, Group and User. Map owners to Group or User references, carry over lifecycle, tags and links, and attach API definitions where the source defines them. Keep the conversion in a script so it can run again when Cortex data changes. Record every field that has no direct equivalent so a person can decide how to handle it. Done means each converted file validates against the Backstage descriptor format and the list of unmapped fields is reviewed and signed off.
Import into a test Backstage instance
Load the converted files into a non-production Backstage instance, so that the catalog reads them through its normal location mechanism. Use the authentication setup that matches your identity provider and avoid guest access, since Backstage documentation advises against it in production. Check that the catalog loads without errors and that entity pages render. Done means the test instance lists the imported entities and the import log shows no unresolved references to owners or systems.
Reconcile counts and ownership before sign-off
This is the verification gate. Compare the entity count in the Backstage test catalog with the inventory from the first step, and list any mismatch by identifier. Then check ownership on every entity: the owning group or user in Backstage must match the owner recorded in the Cortex export, and each owner must resolve to an existing identity. Sample entities for relationships, lifecycle and links. Cutover does not proceed until counts match, every ownership field resolves, and each exception has a documented decision. Done means the platform owner and the service owners who are affected have signed off on the reconciliation report.
Export options for SaaS and self-managed Cortex
SaaS customers reach their catalog through the Cortex REST API, authenticated with credentials issued through their Cortex account. The documented catalog endpoints cover the main read paths: GET /api/v1/catalog lists entities, GET /api/v1/catalog/search finds them, GET /api/v1/catalog/descriptors returns descriptors, and GET /api/v1/catalog/{tagOrId} fetches one entity. Because Cortex hosts the data, the API is the supported route, and you do not need infrastructure access to start.
- Inventory first: Page through
GET /api/v1/catalogto record every entity tag and ID before you pull descriptors. - Bulk descriptors: Use
GET /api/v1/catalog/descriptorsto retrieve the x-cortex descriptor content that feeds the conversion step. - Targeted retries: Use
GET /api/v1/catalog/{tagOrId}to re-fetch any entity that fails conversion. - Credential scope: Ask Cortex which token type your account needs and which entities that token can read.
- Paging and limits: Confirm documented rate limits and pagination behavior before you script a full run.
Review the Cortex catalog entities REST API for parameters and response shapes before you write the script, since field names in responses determine your conversion logic.
Self-managed Cortex runs in your own Kubernetes cluster from a Helm chart, on EKS, AKS, GKE or a locally installed Kubernetes distribution. It also needs a JWT license key and an access token from the Cortex account team, plus a PostgreSQL database. The export still starts with the REST API, but the API is served from your environment, so the network path, TLS and versioning are yours to confirm.
- Same endpoints, confirmed per version: Check that the catalog endpoints in your installed version match the SaaS reference before you rely on them.
- Network path: Run the export from a host inside the cluster network or a bastion, and confirm how your ingress and TLS are configured.
- Token handling: Store the access token in your secrets manager and inject it at runtime, not in scripts or repositories.
- License still applies: The JWT license key remains required, so exporting data does not change your subscription obligations.
- Version record: Record the deployed Cortex version alongside each export so the output can be traced to the API behavior that produced it.
Check the self-managed Cortex documentation for the deployment prerequisites and confirm with your Cortex account team which API endpoint and token type apply to your installation.
Self-managed deployments include a PostgreSQL database in your cluster, so a team may consider reading entity data straight from it. The supplied documentation confirms that the database is required, but it does not describe a supported schema or a supported read path for export. Treat direct database access as something to confirm with Cortex before you build on it, not as an assumed route.
- Why teams consider it: The database sits in your environment and may appear to offer the fastest bulk path.
- Support position: Ask Cortex in writing whether direct reads are supported for your version and whether any database access is appropriate.
- Schema stability: Internal tables can change between releases, so a script built on them can break during an upgrade.
- Access control: Reading tables directly may skip the permission checks the API enforces, so confirm what a database read would expose.
- Load and backups: Large reads can slow the production database, so coordinate with your DBA and use a read replica if one exists.
If Cortex confirms a supported path, document the queries, take a snapshot before the run and validate the output against API counts. If Cortex does not confirm one, use the REST API and accept the slower run.
Validation applies to every deployment model. An export is only useful for migration if you can show that the entities you received match the entities in Cortex at the time of export, and that the converted files preserve ownership and metadata. Plan validation before the first run so that the checks are part of the export, not an afterthought.
- Count reconciliation: Compare entity counts from the list endpoint against the Cortex interface for each entity type.
- Raw archive: Store the raw descriptor exports in version control or an archive with timestamps, so each conversion can be rerun.
- Field diff: After conversion to Backstage files, compare owner, tags and relationships against the source descriptors, using the Backstage descriptor format as the target.
- Change freeze: Ask teams to pause ownership changes in Cortex during the final export, or repeat the export after cutover.
- Retention: Keep the raw exports and validation reports as records for the decommissioning decision.
Before you retire any Cortex access, confirm with your own compliance and records owners how long exports and validation reports must be retained.
Questions teams ask before exporting from Cortex
How much effort does exporting from Cortex take?
The effort depends mainly on how many catalog entities you have and how complete their descriptors are. Each entity must be listed through the REST API with GET /api/v1/catalog, fetched in detail, and then mapped to a Backstage entity. A small catalog with clean descriptors is mostly a scripting task. A large catalog with inconsistent fields, hand-edited records and custom properties needs review time for each group of entities. Ask your team to count entities by type and to sample descriptors from each team before estimating. Those two numbers will explain most of the range in any quote.
What makes a Cortex export harder than expected?
Three things usually slow the work: descriptor quality, ownership gaps and entities that exist only in the UI. Descriptors that use the x-cortex format consistently map cleanly to Backstage catalog-info.yaml files. Entities with missing or stale owners need a decision from a team lead before they can be assigned a spec.owner value. Scorecard rules and custom properties do not translate one to one, so they need a separate rebuild plan. Audit the export for these three gaps first, because they drive most of the rework.
Can our own team export Cortex data without outside help?
Yes, a team with API experience and some Backstage knowledge can usually handle the export itself. The REST API exposes catalog listing, search, descriptor retrieval and single-entity fetches, so the extraction step is a scripting exercise. The harder parts are the mapping rules, the review of ownership data and the validation of the resulting catalog in a test Backstage instance. If nobody on the team has run Backstage before, an implementation partner can shorten the learning curve. DeployOpen plans and implements these engagements under a written, fixed scope.
What should we ask Cortex in writing before we start?
Ask for written confirmation of the export options available on your plan, the API rate limits and any access restrictions on bulk retrieval. Also ask whether descriptors can be exported in full, including the x-cortex fields you rely on, and what happens to your data when your subscription ends. If you run the self-managed edition, confirm the license terms for keeping it running during the export window. Keep the answers in your migration record, since they set the limits of what you can extract.
How long should the cutover overlap between Cortex and Backstage be?
The overlap should be set by four drivers: how many teams depend on Cortex scorecards and reports, how many entities need ownership sign-off, how often the catalog changes during the window, and how many integrations still write to Cortex. More dependent teams, more changing entities and more active integrations all lengthen the overlap. Agree on a clear cutover criteria list with each team lead, then set the overlap length from that list rather than from a fixed calendar guess.
What do engineers and platform owners need to contribute?
Engineers need to confirm ownership, correct descriptors and verify that their services appear with the right dependencies and documentation links in Backstage. Platform owners need to decide the entity model, naming conventions, authentication resolvers and where the Backstage catalog will be hosted. Plan review time for each group, since a mapping error often shows up only when a team looks at its own service. Named reviewers from every team reduce the risk of stale data reaching production.
Do we have to keep paying for Cortex during the export?
Yes, in most cases. Commercial self-managed editions of Cortex still require a vendor license key, so running the product yourself does not remove the subscription. Plan to keep the subscription active until your export is validated and your teams have confirmed the new catalog. Confirm the exact end date and the terms for read-only access in writing with the vendor, because the answer determines whether you pay for an overlap period.
What to plan before the Cortex renewal or termination
The export itself is the easy part. The risk sits in the contract terms, the format of the data you get back, and the state of the catalog while you move it. Work through these cards before you set a cutover date, because each one changes what you export and when.
Confirm the export window and API access
Read the contract for how long API access continues after notice or non-renewal, and whether read access to the catalog is included at all. Ask Cortex to confirm in writing the date after which the REST API and the descriptor endpoints stop responding. Plan your full pull and a verification pass well inside that window, not on its last day.
Get data return formats in writing
Ask the vendor to state in writing which formats they will provide for entities, descriptors, relationships and history, and whether any of it comes as a bulk export rather than through per-entity API calls. Confirm whether custom fields and x-cortex extensions are included. A written answer lets you test the parser against real output before the contract ends.
Freeze descriptor changes during cutover
Set a change freeze on cortex.yaml descriptors and on Cortex entity edits for the period between your baseline export and the final delta export. Without a freeze, an owner change made after your export will not reach the Backstage catalog-info.yaml files, and ownership data drifts silently. Name one owner to approve any exception.
Check license key and token expiry
If you run the self-managed Helm deployment, record the expiry of the JWT license key and the access token issued by the Cortex account team, along with the PostgreSQL backup status. Renewals of these credentials may not match your subscription dates, so an expiry can fall in the middle of your export. Ask the account team to confirm both dates and the renewal process in writing.
Decide on read-only retention
Decide whether the Cortex instance will be kept read-only after the subscription ends, how long, and who can still log in for audit or lookup. Self-managed editions still require the license key, so keeping an instance running may mean keeping a paid or compliant license in place. Document the retention period, the access list and the deletion date in your records of processing.
Map ownership before cutover
Before you convert entities, confirm which Cortex teams, groups and owners correspond to Backstage Group and User entities, and who signs off on each mapping. Owners that exist in Cortex but not in your identity provider will fail sign-in resolution later. Agree the mapping with team leads so the catalog reflects accountable owners on day one.
How to verify the exported catalog is complete
Verification means reconciling the export against the live Cortex portal before anyone deletes or freezes the source. Start with entity counts by kind: count the entities returned by GET /api/v1/catalog for each type in Cortex, then count the Backstage catalog-info.yaml files you generated for each kind, such as Component, API, System, Group and User. Any gap should be traced to a specific entity, a filter you forgot to remove, or a kind you chose not to map. Record the numbers and the reason for every difference in a shared sheet so the reviewer can follow the trail without rerunning the export.
Next, sample entities and check the fields that matter most for ownership. Pick a set that covers each team, each lifecycle stage and any entity with unusual metadata, then compare owner, description, tags and links against the live Cortex page. Check that every relationship, such as a component's system or an API's provider and consumer, resolves to an entity that exists in the new catalog, since a broken reference will show up as an orphan in Backstage. Confirm that every API entity carries its full definition, whether that is an OpenAPI, AsyncAPI, GraphQL or gRPC document, and that each definition was captured in the export rather than replaced by a link you no longer control.
Treat this as a checklist that your team signs off, not an audit or certification. An independent auditor or certification body is the only party that can attest to controls, so the sign-off record should name who checked each item, the date, and the open exceptions. Ask your Cortex account team to confirm which endpoints and fields your subscription and self-managed license expose before you rely on them for completeness, because some data may sit outside the catalog API. Keep the signed checklist with the migration plan so that a later reviewer can see what was verified and what was accepted as a known gap.
How DeployOpen scopes and delivers a Cortex data export
DeployOpen approaches a Cortex data export as a fixed-scope engagement inside your own environment. We agree in writing which catalog entities, descriptor fields and ownership records move, then plan, build, test and document the export and the Backstage catalog-info translation before any work starts.
How we scope
- Inventory the Cortex entity types, teams and descriptor fields your catalog actually uses before any export code is written
- Agree in writing which REST API endpoints, entities and descriptor formats fall inside the export and which do not
- Confirm where the exported files will live, who can access them, and how the work fits your cutover window
How we build
- Build the export scripts against the Cortex catalog entities REST API, running them under a read-only credential you control
- Translate exported descriptors into Backstage catalog-info files and check each entity kind and relation against the descriptor format
- Test the output on a non-production Backstage instance and reconcile entity counts and ownership with the source data
How we hand over
- Deliver the export scripts, mapping tables and generated catalog-info files with documentation of every field conversion
- Document the reconciliation results, known gaps such as fields with no direct Backstage equivalent, and the steps to rerun the export
- Walk your platform and service owners through the handover so the team can repeat or audit the export without us
How we support
- Fixed-scope delivery is agreed in writing, so the deliverables and boundaries are known before the engagement begins
- Ongoing support, upgrades and continuous testing of the resulting Backstage catalog are available as a retainer
- Ask any provider, including us, to confirm in writing how exports are timed against your Cortex license and subscription terms

