# express-endpoints-collection

> This package provides easy to use helper for creating API endpoints in Express with TypeScript inference, validation and OpenAPI 3 schema out of the box.

Latest version **2.1.0** (published 2026-09-23) · (AGPL-3.0-only OR LicenseRef-Commercial) license · 0 weekly downloads

## Install

```sh
npm install express-endpoints-collection
pnpm add express-endpoints-collection
yarn add express-endpoints-collection
bun add express-endpoints-collection
```

## Health

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

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

Warnings: low downloads; no esm support.

## Facts

| | |
|---|---|
| Version | 2.1.0 |
| Published | 2026-09-23 |
| First published | 2024-06-29 |
| Weekly downloads | 0 |
| License | (AGPL-3.0-only OR LicenseRef-Commercial) |
| TypeScript types | bundled |
| Module format | CommonJS |
| Node | >=18.0.0 |
| Dependencies | 8 |
| Unpacked size | 116.3 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1 |
| Author | pilotpirxie |
| Maintainers | pilotpirxie |
| Keywords | express, endpoints, collection, api, rest, restful, openapi, swagger, zod, typescript, ts, validation, inference |

## Links

- npm: https://www.npmjs.com/package/express-endpoints-collection
- Repository: https://github.com/pilotpirxie/express-endpoints-collection
- Homepage: https://github.com/pilotpirxie/express-endpoints-collection#readme
- Issues: https://github.com/pilotpirxie/express-endpoints-collection/issues
- npm.io page: https://npm.io/package/express-endpoints-collection

## Dependencies (8)

- [zod](https://npm.io/package/zod.md) ^4.3.6
- [express](https://npm.io/package/express.md) ^5.2.1
- [js-yaml](https://npm.io/package/js-yaml.md) ^4.1.0
- [node-cache](https://npm.io/package/node-cache.md) ^5.1.2
- [jsonwebtoken](https://npm.io/package/jsonwebtoken.md) ^9.0.2
- [express-rate-limit](https://npm.io/package/express-rate-limit.md) ^8.7.0
- [@types/jsonwebtoken](https://npm.io/package/@types/jsonwebtoken.md) ^9.0.8
- [@asteasolutions/zod-to-openapi](https://npm.io/package/@asteasolutions/zod-to-openapi.md) ^8.5.0

## Alternatives

- [@regle/core](https://npm.io/package/@regle/core.md) — 47.0K weekly downloads
- [typeof-arguments](https://npm.io/package/typeof-arguments.md) — 12.5K weekly downloads
- [@lokalise/projects-engine-contracts](https://npm.io/package/@lokalise/projects-engine-contracts.md) — 978 weekly downloads
- [@osjwnpm/nam-laboriosam-quibusdam](https://npm.io/package/@osjwnpm/nam-laboriosam-quibusdam.md) — 70 weekly downloads
- [@oridune/validator](https://npm.io/package/@oridune/validator.md) — 16 weekly downloads

## Recent versions

- 2.1.0 (latest) — 2026-09-23
- 2.0.0 — 2026-04-04
- 1.0.28 — 2025-01-30
- 1.0.27 — 2024-08-23
- 1.0.26 — 2024-08-23
- 1.0.25 — 2024-08-22
- 1.0.24 — 2024-08-22
- 1.0.23 — 2024-08-21
- 1.0.22 — 2024-08-21
- 1.0.21 — 2024-08-21
- 1.0.20 — 2024-08-21
- 1.0.19 — 2024-08-21
- 1.0.18 — 2024-08-21
- 1.0.17 — 2024-08-21
- 1.0.16 — 2024-08-21
- … 16 more at https://npm.io/package/express-endpoints-collection/versions

## README

# express-endpoints-collection

## Description

This package provides easy to use helper for creating API endpoints in Express with TypeScript inference, validation and OpenAPI 3 schema out of the box.

No need to duplicate OpenAPI definitions in your codebase. Just define your API endpoints and automatically generate OpenAPI 3 schema.

You can configure exposed endpoints, request and response schemas, and validation rules.

![output](./img/output1.png)

For support of zod v3 and express v4 use 1.0.28

## Features

- Fully typed endpoints (TypeScript hints and checks) for Express v5
  - Request body
  - Response body
  - Query parameters
  - Path parameters
  - Headers
- Automatic OpenAPI 3.0 schema generation
- Request and response validation using Zod v4
- Full middleware support
- Minimal setup

## Installation

```shell
npm install express-endpoints-collection

# or

yarn add express-endpoints-collection

# or

pnpm add express-endpoints-collection
```

## Usage

```typescript
import express, { Express } from "express";
import bodyParser from "body-parser";
import { z } from "zod";
import { EndpointsCollection } from "express-endpoints-collection";
import { generateOpenAPI } from "express-endpoints-collection/generator";

// 1. Create express app
const app: Express = express();
app.use(bodyParser.json());

// 2. Create endpoints collection, this will store all your endpoints
const endpointsCollection = new EndpointsCollection();

// 3. Add new endpoint
endpointsCollection.post(
  "/add",
  {
    inputSchema: {
      body: z.object({
        a: z.number(),
        b: z.number(),
      }),
    },
    outputSchema: [
      {
        status: 200,
        body: z.object({
          result: z.number(),
        }),
      },
    ],
    summary: "Add two numbers",
  },
  // 4. req and res are fully typed!
  (req, res) => {
    const { a, b } = req.body;
    res.json({ result: a + b });
  },
);

// 5. Collection creates its own router, to use it just add it to your app
app.use(endpointsCollection.getRouter());

// 6. Expose OpenAPI 3 schema
app.get("/openapi", (req, res) => {
  res.setHeader("Content-Type", "text/yaml");
  res.send(
    generateOpenAPI({
      title: "Minimal demo",
      version: "1.0.0",
      endpoints: endpointsCollection.getEndpoints(),
      servers: ["http://localhost:3000"],
    }),
  );
});

// 7. Start the server and done!
app.listen(3000, () => {
  console.info(`Server is running on port http://localhost:3000`);
});
```

it will generate OpenAPI 3 definition as follow:

```yaml
openapi: 3.0.0
info:
  title: Minimal demo
  version: 1.0.0
components:
  schemas: {}
  parameters: {}
paths:
  /add:
    post:
      summary: Add two numbers
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                a:
                  type: number
                b:
                  type: number
              required:
                - a
                - b
      responses:
        "200":
          description: Response for status code 200
          content:
            application/json:
              schema:
                type: object
                properties:
                  result:
                    type: number
                required:
                  - result
```

or as JSON

```json
{
  "openapi": "3.0.0",
  "info": {
    "title": "Minimal demo",
    "version": "1.0.0"
  },
  "components": {
    "schemas": {},
    "parameters": {}
  },
  "paths": {
    "/add": {
      "post": {
        "summary": "Add two numbers",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "a": {
                    "type": "number"
                  },
                  "b": {
                    "type": "number"
                  }
                },
                "required": ["a", "b"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Response for status code 200",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "number"
                    }
                  },
                  "required": ["result"]
                }
              }
            }
          }
        }
      }
    }
  }
}
```

## Example

![output](./img/output0.png)

Type inference and checks:

![infer0](./img/infer0.png)

![infer1](./img/infer1.png)

## Built-in middlewares

Import `z` from this package so request schemas use the same Zod instance the collection validates with.

```typescript
import {
  defineMiddlewares,
  EndpointsCollection,
  z,
} from "express-endpoints-collection";

const api = defineMiddlewares({
  customErrorHandler: (_error, details) => ({
    error: "ValidationError",
    details,
  }),
  middlewares: {
    requestLogger: { enabled: true },
    jwt: { secret: process.env.JWT_SECRET ?? "dev-secret" },
    cache: { stdTTL: 60, checkperiod: 120 },
    rateLimit: { windowMs: 60_000, limit: 30 },
    errorHandler: { enabled: true },
  },
});

const shops = new EndpointsCollection({
  collectionPrefix: "/shops",
  ...api,
});

const account = new EndpointsCollection({
  collectionPrefix: "/account",
  ...api,
  middlewares: {
    ...api.middlewares,
    jwt: { ...api.middlewares.jwt, enabled: true },
  },
});

shops.get(
  "/",
  {
    outputSchema: [{ status: 200, body: z.object({ ok: z.boolean() }) }],
    middlewares: { cache: true, rateLimit: { limit: 10 } },
  },
  (_req, res) => {
    res.json({ ok: true });
  },
);
```

Collection `jwt: { secret }` with `enabled` omitted is settings only; routes stay open until they set `jwt: true` or a partial such as `jwt: { required: false }`. Collection `enabled: true` applies that middleware to every route unless the route sets `false`. The same rules apply to `requestLogger`, `cache`, `rateLimit`, and `errorHandler`. Per-route `cache: true` or `rateLimit: { limit: 10 }` still opt in when collection `enabled` is omitted.

Replacing `jwt` with `{ enabled: true }` drops `secret`. Spread the preset first: `jwt: { ...api.middlewares.jwt, enabled: true }`.

Other middleware still goes on `beforeInputValidation`, `afterInputValidation`, or `beforeResponse`. A cache hit returns before `beforeInputValidation`, so that hook does not run for a stored response. A per-route `checkperiod` is ignored. `stdTTL` on a route is the TTL for that route's cache entries. Client options such as `checkperiod` belong on the collection.

## License

This software is licensed under the GNU Affero General Public License v3.0. See [LICENSE](LICENSE).

Anyone may use it under AGPLv3, including in a commercial product, if they comply with that license.

For a written license without AGPL copyleft, contact the author on [GitHub](https://github.com/pilotpirxie). Until that agreement exists, AGPLv3 applies.

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