# openapi-backend

> Build, Validate, Route, Authenticate and Mock using OpenAPI definitions. Framework-agnostic

Latest version **5.20.1** (published 2026-08-23) · MIT license · 0 weekly downloads

## Install

```sh
npm install openapi-backend
pnpm add openapi-backend
yarn add openapi-backend
bun add openapi-backend
```

## Health

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

Positive: has types; no vulnerabilities; has provenance; recently updated; high maintenance score; high quality score.

Warnings: low downloads; no esm support.

## Facts

| | |
|---|---|
| Version | 5.20.1 |
| Published | 2026-08-23 |
| First published | 2018-10-27 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Node | >=20.0.0 |
| Dependencies | 10 |
| Unpacked size | 160 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 685 |
| Author | Viljami Kuosmanen |
| Maintainers | anttiviljami |
| Keywords | openapi, swagger, server, router, validation, mock, express, hapi, koa, serverless, lambda, azure |

## Links

- npm: https://www.npmjs.com/package/openapi-backend
- Repository: https://github.com/openapistack/openapi-backend
- Homepage: https://openapistack.co
- Issues: https://github.com/openapistack/openapi-backend/issues
- Funding: https://github.com/sponsors/anttiviljami
- npm.io page: https://npm.io/package/openapi-backend

## Dependencies (10)

- [qs](https://npm.io/package/qs.md) ^6.15.0
- [ajv](https://npm.io/package/ajv.md) ^8.6.2
- [cookie](https://npm.io/package/cookie.md) ^1.0.1
- [lodash](https://npm.io/package/lodash.md) ^4.17.15
- [bath-es5](https://npm.io/package/bath-es5.md) ^3.0.3
- [openapi-types](https://npm.io/package/openapi-types.md) ^12.0.2
- [mock-json-schema](https://npm.io/package/mock-json-schema.md) ^1.0.7
- [dereference-json-schema](https://npm.io/package/dereference-json-schema.md) ^0.2.1
- [openapi-schema-validator](https://npm.io/package/openapi-schema-validator.md) ^12.0.0
- [@apidevtools/json-schema-ref-parser](https://npm.io/package/@apidevtools/json-schema-ref-parser.md) ^11.1.0

## Alternatives

- [express-promise-router](https://npm.io/package/express-promise-router.md) — 736.1K weekly downloads
- [next-usequerystate](https://npm.io/package/next-usequerystate.md) — 29.8K weekly downloads
- [@bitkyc08/opencodex](https://npm.io/package/@bitkyc08/opencodex.md) — 4.6K weekly downloads
- [lynkr](https://npm.io/package/lynkr.md) — 575 weekly downloads
- [baremetal.js](https://npm.io/package/baremetal.js.md) — 42 weekly downloads

## Recent versions

- 5.20.1 (latest) — 2026-08-23
- 5.20.0 — 2026-07-29
- 5.19.0 — 2026-07-25
- 5.18.0 — 2026-06-24
- 5.17.0 — 2026-05-17
- 5.16.1 — 2026-02-22
- 5.16.0 — 2026-02-22
- 5.15.0 — 2025-08-20
- 5.14.0 — 2025-08-13
- 5.13.0 — 2025-07-01
- 5.12.0 — 2025-04-14
- 5.11.1 — 2024-11-06
- 5.11.0 — 2024-09-10
- 5.10.6 — 2024-01-27
- 5.10.5 — 2023-10-09
- … 122 more at https://npm.io/package/openapi-backend/versions

## README

<span id="npm--fix-hidden-readme-header"></span>

<h1 align="center"><img alt="openapi-backend" src="https://github.com/openapistack/openapi-backend/raw/main/header.png" style="max-width:50rem"></h1>

[![CI](https://github.com/openapistack/openapi-backend/workflows/CI/badge.svg)](https://github.com/openapistack/openapi-backend/actions?query=workflow%3ACI)
[![License](http://img.shields.io/:license-mit-blue.svg)](https://github.com/openapistack/openapi-backend/blob/main/LICENSE)
[![npm version](https://img.shields.io/npm/v/openapi-backend.svg)](https://www.npmjs.com/package/openapi-backend)
[![npm downloads](https://img.shields.io/npm/dw/openapi-backend.svg)](https://www.npmjs.com/package/openapi-backend)
[![Libraries.io dependency status for latest release](https://img.shields.io/librariesio/release/npm/openapi-backend.svg)](https://www.npmjs.com/package/openapi-backend?activeTab=dependencies)
![npm type definitions](https://img.shields.io/npm/types/openapi-backend.svg)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/openapistack/openapi-backend)
[![Buy me a coffee](https://img.shields.io/badge/donate-buy%20me%20a%20coffee-orange)](https://buymeacoff.ee/anttiviljami)

<p align="center"><b>Build, Validate, Route, Authenticate, and Mock using OpenAPI definitions.</b></p>

<p align="center">OpenAPI Backend is a Framework-agnostic middleware tool for building beautiful APIs with <a href="https://github.com/OAI/OpenAPI-Specification">OpenAPI Specification</a>.</p>

<p align="center"><i>Battle-tested in production. <a href="https://openapistack.co/users/">See who uses openapi-stack →</a></i></p>

## Features

- [x] Build APIs by describing them in [OpenAPI specification](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md)
- [x] Register handlers for [operationIds](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#fixed-fields-8)
to route requests in your favourite Node.js backend
- [x] Use [JSON Schema](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#data-types) to validate
API requests and/or responses. OpenAPI Backend uses the [AJV](https://ajv.js.org/) library under the hood for performant validation
- [x] Register Auth / Security Handlers for [OpenAPI Security Schemes](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securitySchemeObject)
to authorize API requests
- [x] Auto-mock API responses using [OpenAPI examples objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#example-object)
or [JSON Schema definitions](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#schema-object)
- [x] Built with TypeScript, types included
- [x] Optimised runtime routing and validation. **No generated code!**
- [x] OpenAPI 3.1 support

## Documentation

**New!** OpenAPI Backend documentation is now found on [openapistack.co](https://openapistack.co)

https://openapistack.co/docs/openapi-backend/intro

## Quick Start

Full [example projects](https://github.com/openapistack/openapi-backend/tree/main/examples) included in the repo

```
npm install --save openapi-backend
```

```javascript
import OpenAPIBackend from 'openapi-backend';

// create api with your definition file or object
const api = new OpenAPIBackend({ definition: './petstore.yml' });

// register your framework specific request handlers here
api.register({
  getPets: (c, req, res) => res.status(200).json({ result: 'ok' }),
  getPetById: (c, req, res) => res.status(200).json({ result: 'ok' }),
  validationFail: (c, req, res) => res.status(400).json({ err: c.validation.errors }),
  notFound: (c, req, res) => res.status(404).json({ err: 'not found' }),
});

// initalize the backend
api.init();
```

### Express

```javascript
import express from 'express';

const app = express();
app.use(express.json());
app.use((req, res) => api.handleRequest(req, req, res));
app.listen(9000);
```

[See full Express example](https://github.com/openapistack/openapi-backend/tree/main/examples/express)

[See full Express TypeScript example](https://github.com/openapistack/openapi-backend/tree/main/examples/express-typescript)

### AWS Serverless (Lambda)

```javascript
// API Gateway Proxy handler
module.exports.handler = (event, context) =>
  api.handleRequest(
    {
      method: event.httpMethod,
      path: event.path,
      query: event.queryStringParameters,
      body: event.body,
      headers: event.headers,
    },
    event,
    context,
  );
```

[See full AWS SAM example](https://github.com/openapistack/openapi-backend/tree/main/examples/aws-sam)

[See full AWS CDK example](https://github.com/openapistack/openapi-backend/tree/main/examples/aws-cdk)

[See full SST example](https://github.com/openapistack/openapi-backend/tree/main/examples/aws-sst)

[See full Serverless Framework example](https://github.com/openapistack/openapi-backend/tree/main/examples/serverless-framework)

### Azure Function

```javascript
module.exports = (context, req) =>
  api.handleRequest(
    {
      method: req.method,
      path: req.params.path,
      query: req.query,
      body: req.body,
      headers: req.headers,
    },
    context,
    req,
  );
```

[See full Azure Function example](https://github.com/openapistack/openapi-backend/tree/main/examples/azure-function)

### Fastify

```ts
import fastify from 'fastify';

fastify.route({
  method: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
  url: '/*',
  handler: async (request, reply) =>
    api.handleRequest(
      {
        method: request.method,
        path: request.url,
        body: request.body,
        query: request.query,
        headers: request.headers,
      },
      request,
      reply,
    ),
});
fastify.listen();
```

[See full Fastify example](https://github.com/openapistack/openapi-backend/tree/main/examples/fastify)

### Hapi

```javascript
import Hapi from '@hapi/hapi';

const server = new Hapi.Server({ host: '0.0.0.0', port: 9000 });
server.route({
  method: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
  path: '/{path*}',
  handler: (req, h) =>
    api.handleRequest(
      {
        method: req.method,
        path: req.path,
        body: req.payload,
        query: req.query,
        headers: req.headers,
      },
      req,
      h,
    ),
});
server.start();
```

[See full Hapi example](https://github.com/openapistack/openapi-backend/tree/main/examples/hapi-typescript)


### Koa

```javascript
import Koa from 'koa';
import bodyparser from 'koa-bodyparser';

const app = new Koa();

app.use(bodyparser());
app.use((ctx) =>
  api.handleRequest(
    ctx.request,
    ctx,
  ),
);
app.listen(9000);
```

[See full Koa example](https://github.com/openapistack/openapi-backend/tree/main/examples/koa)

## Registering Handlers for Operations

Handlers are registered for [`operationIds`](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.2.md#fixed-fields-8)
found in the OpenAPI definitions. You can register handlers as shown above with [`new OpenAPIBackend()`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#parameter-optshandlers)
constructor opts, or using the [`register()`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#registeroperationid-handler)
method.

```javascript
async function getPetByIdHandler(c, req, res) {
  const id = c.request.params.id;
  const pet = await pets.getPetById(id);
  return res.status(200).json({ result: pet });
}
api.register('getPetById', getPetByIdHandler);
// or
api.register({
  getPetById: getPetByIdHandler,
});
```

Operation handlers are passed a special [Context object](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#context-object)
as the first argument, which contains the parsed request, the
matched API operation and input validation results. The other arguments in the example above are Express-specific
handler arguments.

## Request validation

The easiest way to enable request validation in your API is to register a [`validationFail`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#validationfail-handler)
handler.

```javascript
function validationFailHandler(c, req, res) {
  return res.status(400).json({ status: 400, err: c.validation.errors });
}
api.register('validationFail', validationFailHandler);
```

Once registered, this handler gets called if any JSON Schemas in either operation parameters (in: path, query, header,
cookie) or requestPayload don't match the request.

The context object `c` gets a `validation` property with the [validation result](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#validationresult-object).

### Controlling when requests get validated

Request validation is enabled by default. Pass `validate: false` to turn it off entirely, which also skips building the
Ajv validators at startup.

```javascript
const api = new OpenAPIBackend({ definition: './petstore.yml', validate: false });
```

You can also pass a predicate to decide per request. It receives the context object followed by the same handler
arguments you pass to `handleRequest`, and validation runs only when it returns `true`.

```javascript
const api = new OpenAPIBackend({
  definition: './petstore.yml',
  // skip validation for internal traffic, validate everything else
  validate: (c, req, res) => !req.headers['x-internal-request'],
});

api.handleRequest(req, req, res);
```

Note that type coercion happens as part of validation, so when `coerceTypes` is enabled, requests your predicate skips
won't have their path and query parameters coerced either.

## Response validation

OpenAPIBackend doesn't automatically perform response validation for your handlers, but you can register a
[`postResponseHandler`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#postresponsehandler-handler)
to add a response validation step using [`validateResponse`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#validateresponseres-operation).

```javascript
api.register({
  getPets: (c) => {
    // when a postResponseHandler is registered, your operation handlers' return value gets passed to context.response
    return [{ id: 1, name: 'Garfield' }];
  },
  postResponseHandler: (c, req, res) => {
    const valid = c.api.validateResponse(c.response, c.operation);
    if (valid.errors) {
      // response validation failed
      return res.status(502).json({ status: 502, err: valid.errors });
    }
    return res.status(200).json(c.response);
  },
});
```

It's also possible to validate the response headers using [`validateResponseHeaders`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#validateresponseheadersheaders-operation-opts).

```javascript
api.register({
  getPets: (c) => {
    // when a postResponseHandler is registered, your operation handlers' return value gets passed to context.response
    return [{ id: 1, name: 'Garfield' }];
  },
  postResponseHandler: (c, req, res) => {
    const valid = c.api.validateResponseHeaders(res.headers, c.operation, {
      statusCode: res.statusCode,
      setMatchType: 'exact',
    });
    if (valid.errors) {
      // response validation failed
      return res.status(502).json({ status: 502, err: valid.errors });
    }
    return res.status(200).json(c.response);
  },
});
```

## Auth / Security Handlers

If your OpenAPI definition contains [Security Schemes](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securitySchemeObject)
you can register security handlers to handle authorization for your API:

```yaml
components:
  securitySchemes:
  - ApiKey:
      type: apiKey
      in: header
      name: x-api-key
security:
  - ApiKey: []
```

```javascript
api.registerSecurityHandler('ApiKey', (c) => {
  const authorized = c.request.headers['x-api-key'] === 'SuperSecretPassword123';
  // truthy return values are interpreted as auth success
  // you can also add any auth information to the return value
  return authorized;
});
```

The authorization status and return values of each security handler can be
accessed via the [Context Object](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#context-object)

You can also register an [`unauthorizedHandler`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#unauthorizedhandler-handler)
to handle unauthorized requests.

```javascript
api.register('unauthorizedHandler', (c, req, res) => {
  return res.status(401).json({ err: 'unauthorized' })
});
```

See examples:
- [API Key auth (express)](https://github.com/openapistack/openapi-backend/tree/main/examples/express-apikey-auth)
- [JWT auth (express)](https://github.com/openapistack/openapi-backend/tree/main/examples/express-jwt-auth)

## Mocking API responses

Mocking APIs just got really easy with OpenAPI Backend! Register a [`notImplemented`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#notimplemented-handler)
handler and use [`mockResponseForOperation()`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md##mockresponseforoperationoperationid-opts)
to generate mock responses for operations with no custom handlers specified yet:

```javascript
api.register('notImplemented', (c, req, res) => {
  const { status, mock } = c.api.mockResponseForOperation(c.operation.operationId);
  return res.status(status).json(mock);
});
```

OpenAPI Backend supports mocking responses using both OpenAPI example objects and JSON Schema:
```yaml
paths:
  '/pets':
    get:
      operationId: getPets
      summary: List pets
      responses:
        200:
          $ref: '#/components/responses/PetListWithExample'
  '/pets/{id}':
    get:
      operationId: getPetById
      summary: Get pet by its id
      responses:
        200:
          $ref: '#/components/responses/PetResponseWithSchema'
components:
  responses:
    PetListWithExample:
      description: List of pets
      content:
        'application/json':
          example:
            - id: 1
              name: Garfield
            - id: 2
              name: Odie
    PetResponseWithSchema:
      description: A single pet
      content:
        'application/json':
          schema:
            type: object
            properties:
              id:
                type: integer
                minimum: 1
              name:
                type: string
                example: Garfield
```

The example above will yield:
```javascript
api.mockResponseForOperation('getPets'); // => { status: 200, mock: [{ id: 1, name: 'Garfield' }, { id: 2, name: 'Odie' }]}
api.mockResponseForOperation('getPetById'); // => { status: 200, mock: { id: 1, name: 'Garfield' }}
```

[See full Mock API example on Express](https://github.com/openapistack/openapi-backend/tree/main/examples/express-ts-mock)

## Commercial support

For assistance with integrating openapi-backend in your company, reach out at support@openapistack.co.

## Contributing

OpenAPI Backend is Free and Open Source Software. Issues and pull requests are more than welcome!

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