# Validate catalog entities

> How to validate catalog entities against the Backstage schema using the validate-entity API endpoint

*Published: 2026-02-10*


## Overview

Roadie provides an API endpoint that validates catalog entities against the entity schema before they are registered in the catalog. This is useful when your scaffolder template generates catalog entity descriptor files and you want to ensure they are valid before proceeding with further steps like committing them to a repository or registering them.

The endpoint accepts a full catalog entity as JSON and returns validation results, letting you catch schema errors early.

## Actions used

- `http:backstage:request`

You can check the available actions if you visit `/create/actions`.

The request body is the full catalog entity you want to validate. It supports all standard entity kinds (Component, API, Resource, System, etc.) and any custom kinds configured in your Roadie instance.

## Using the endpoint in a scaffolder template

You can call the validation endpoint from a scaffolder template using the `http:backstage:request` action. This lets you validate an entity that the template is about to create.

### Minimal example

```yaml
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: create-and-validate-component
  title: Create and validate a Component
  description: Creates a new Component entity and validates it before registering
spec:
  owner: group:default/engineering
  type: service

  parameters:
    - title: Component details
      required:
        - name
        - owner
        - lifecycle
      properties:
        name:
          title: Name
          type: string
        description:
          title: Description
          type: string
        owner:
          title: Owner
          type: string
          ui:field: OwnerPicker
        lifecycle:
          title: Lifecycle
          type: string
          enum:
            - experimental
            - production
            - deprecated

  steps:
    - id: validate-entity
      name: Validate catalog entity
      action: http:backstage:request
      input:
        method: POST
        path: /catalog/validate-entity
        headers:
          content-type: 'application/json'
        body:
          apiVersion: backstage.io/v1alpha1
          kind: Component
          metadata:
            name: ${{ parameters.name }}
            description: ${{ parameters.description }}
            annotations:
              github.com/project-slug: my-org/${{ parameters.name }}
          spec:
            type: service
            lifecycle: ${{ parameters.lifecycle }}
            owner: ${{ parameters.owner }}

    - id: log-validation-result
      name: Log validation result
      action: debug:log
      input:
        message: 'Validation result: ${{ steps["validate-entity"].output.body | dump }}'
```

### Breakdown

The key step is the `http:backstage:request` call to the validation endpoint:

```yaml
- id: validate-entity
  name: Validate catalog entity
  action: http:backstage:request
  input:
    method: POST
    path: /api/catalog/validate-entity
    headers:
      content-type: 'application/json'
    body:
      apiVersion: backstage.io/v1alpha1
      kind: Component
      metadata:
        name: ${{ parameters.name }}
        description: ${{ parameters.description }}
      spec:
        type: service
        lifecycle: ${{ parameters.lifecycle }}
        owner: ${{ parameters.owner }}
```

- **`input.method`**: Must be `POST`.
- **`input.path`**: The validation endpoint path `/catalog/validate-entity`.
- **`input.headers`**: Set the content type to `application/json`.
- **`input.body`**: The full catalog entity to validate. You can use scaffolder parameter values with `${{ parameters.* }}` to build the entity dynamically.

The endpoint always returns a `200` status code. The response body contains a `valid` boolean and, when validation fails, an `errors` array with details about the validation errors:

```json
{
  "valid": false,
  "errors": [
    "<root> must have required property 'kind' - missingProperty: kind"
  ]
}
```

You can access the result via `${{ steps["validate-entity"].output.body }}`.

## Request body

The request body is a standard Backstage catalog entity. At minimum it must include:

| Field | Description |
| --- | --- |
| `apiVersion` | The entity API version, typically `backstage.io/v1alpha1` |
| `kind` | The entity kind (not required in the request, but recommended) |
| `metadata.name` | The entity name |
| `spec` | The entity spec, varies by kind |

The endpoint validates the full entity structure including metadata, annotations, spec fields, and relations. It does not check whether referenced entities (like owners or systems) actually exist in the catalog.

## Further reading

- [Backstage Entity Descriptor Format](https://backstage.io/docs/features/software-catalog/descriptor-format)
- [Modeling entities in Roadie](/docs/catalog/modeling-entities/)
- [Validating catalog files with the GitHub app](/docs/catalog/validator/)
- [API Authorization](/docs/api/authorization/)
- [Call an external API recipe](/docs/scaffolder/recipes/call-external-api/)
