# @backstage/backend-openapi-utils

> OpenAPI typescript support.

Latest version **0.7.1** (published 2026-08-18) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install @backstage/backend-openapi-utils
pnpm add @backstage/backend-openapi-utils
yarn add @backstage/backend-openapi-utils
bun add @backstage/backend-openapi-utils
```

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score; high quality score; popular repo.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.7.1 |
| Published | 2026-08-18 |
| First published | 2023-04-07 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 16 |
| Unpacked size | 171.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 34399 |
| Maintainers | patriko, freben, marcuseide |

## Links

- npm: https://www.npmjs.com/package/@backstage/backend-openapi-utils
- Repository: https://github.com/backstage/backstage
- Homepage: https://backstage.io
- npm.io page: https://npm.io/package/@backstage/backend-openapi-utils

## Dependencies (16)

- [ajv](https://npm.io/package/ajv.md) ^8.16.0
- [lodash](https://npm.io/package/lodash.md) ^4.17.21
- [express](https://npm.io/package/express.md) ^4.22.0
- [mockttp](https://npm.io/package/mockttp.md) ^3.13.0
- [get-port](https://npm.io/package/get-port.md) ^5.1.1
- [openapi3-ts](https://npm.io/package/openapi3-ts.md) ^3.1.2
- [openapi-merge](https://npm.io/package/openapi-merge.md) ^1.3.2
- [@types/express](https://npm.io/package/@types/express.md) ^4.17.6
- [@backstage/types](https://npm.io/package/@backstage/types.md) ^1.2.2
- [@backstage/errors](https://npm.io/package/@backstage/errors.md) ^1.3.1
- [json-schema-to-ts](https://npm.io/package/json-schema-to-ts.md) ^3.0.0
- [express-promise-router](https://npm.io/package/express-promise-router.md) ^4.1.0
- [express-openapi-validator](https://npm.io/package/express-openapi-validator.md) ^5.5.8
- [@apidevtools/swagger-parser](https://npm.io/package/@apidevtools/swagger-parser.md) ^10.1.0
- [@backstage/backend-plugin-api](https://npm.io/package/@backstage/backend-plugin-api.md) ^1.10.0
- [@types/express-serve-static-core](https://npm.io/package/@types/express-serve-static-core.md) ^4.17.5

## Recent versions

- 0.7.1 (latest) — 2026-08-18
- 0.0.0-nightly-20260909022715 (nightly) — 2026-09-09
- 0.7.2-next.0 (next) — 2026-09-01
- 0.0.0-nightly-20260904022803 — 2026-09-04
- 0.0.0-nightly-20260902024315 — 2026-09-02
- 0.0.0-nightly-20260818023149 — 2026-08-18
- 0.0.0-nightly-20260817023522 — 2026-08-17
- 0.0.0-nightly-20260816023538 — 2026-08-16
- 0.0.0-nightly-20260815023121 — 2026-08-15
- 0.0.0-nightly-20260814030239 — 2026-08-14
- 0.0.0-nightly-20260813030414 — 2026-08-13
- 0.0.0-nightly-20260812030228 — 2026-08-12
- 0.0.0-nightly-20260811025108 — 2026-08-11
- 0.0.0-nightly-20260810025551 — 2026-08-10
- 0.0.0-nightly-20260809025047 — 2026-08-09
- … 1043 more at https://npm.io/package/@backstage/backend-openapi-utils/versions

## README

# @backstage/backend-openapi-utils

## Summary

This package is meant to provide a typed Express router for an OpenAPI spec. Based on the [`oatx`](https://github.com/varanauskas/oatx) library and adapted to override Express values.

Only supports OpenAPI 3.1 specifications.

## Getting Started

### Configuration

1. Run `yarn --cwd <package-dir> backstage-cli package schema openapi generate` to translate your `src/schema/openapi.yaml` to a new Typescript file in `src/schema/openapi.generated.ts`. The command will try to execute both a lint and prettier step on the generated file, where applicable.

2. In your plugin's `src/service/createRouter.ts`,

```ts
import { createOpenApiRouter } from '../schema/openapi.generated';
// ...
export function createRouter() {
  const router = createOpenApiRouter();
  // add routes to router, it's just an express router.
  return router;
}
```

3. Add `@backstage/backend-openapi-utils` to your `package.json`'s `dependencies`.

Why do I need to add this to `dependencies`? If you check the `src/schema/openapi.generated.ts` file, we're creating a router stub for you with the `@backstage/backend-openapi-utils` package.

### Customization

If the out of the box `router` doesn't work, you can do the following,

```ts
import { createOpenApiRouter } from '../schema/openapi.generated';
// ...
export function createRouter() {
  // See https://github.com/cdimascio/express-openapi-validator/wiki/Documentation for available options.
  const router = createOpenApiRouter(validatorOptions);
  // add routes to router, it's just an express router.
  return router;
}
```

If you need even more control -- say for example you wanted to update the spec at runtime -- you can do the following,

```ts
import { spec } from '../schema/openapi.generated';
import { createValidatedOpenApiRouter } from '@backstage/backend-openapi-utils';
// ...
export function createRouter() {
  // Update the spec here.
  const newSpec = { ...spec, myproperty123: 123 };

  // See https://github.com/cdimascio/express-openapi-validator/wiki/Documentation for available options.
  const router = createValidatedOpenApiRouter<typeof newSpec>(
    newSpec,
    validatorOptions,
  );
  // add routes to router, it's just an express router.
  return router;
}
```

## FAQs

### Why am I getting `unknown` as the type for a response?

This can happen when you have a `charset` defined in your `response.content` section. Something like `response.content['application/json; charset=utf-8:']` will cause this issue.

## INTERNAL

### Limitations

1. `as const` makes all fields `readonly`
   To ensure a good DX of using a simple imported JSON spec, we want to remove any type issues between `readonly` arrays and mutable arrays. Typescript does not allow them to be compared, so converting all imports from the `openapi3-ts` library to `readonly` is important. This is achieved through the `ImmutableObject` type in `types/immutable.ts`.

```ts
...
// We want an interface like this,
Router() as ApiRouter<typeof spec>

// Not an interface like this,
Router() as ApiRouter<DeepWritable<typeof spec>>
...
```

## Future Work

### Response Validation

This is a murky ground and something that will take a while to gain adoption. For now, keep responses in the spec and at the type level, but will need to work to drive adoption of response validation.

### Common Error Format

With the new `createRouter` method, we can start to control error response formats for input and coercion errors.

---
_Source: https://npm.io/package/@backstage/backend-openapi-utils · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
