
Company News
Free Business Plan Upgrades for Open Source Maintainers
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.
Framework-agnostic API versioning with RFC 8594 Sunset and RFC 9745 Deprecation headers
Framework-agnostic API versioning with full RFC compliance.
Supports RFC 8594 (Sunset header), RFC 9745 (Deprecation header), and three version extraction strategies. Works with Hono, Fastify, Express, and any framework using Web Standards Request/Response.
APIs evolve. Clients need time to migrate. versionkit gives you:
npm install versionkit
| Strategy | Source | Example |
|---|---|---|
header | Custom request header | Api-Version: 2025-01-01 |
url | URL path prefix | /v2/users |
accept | Accept header media type | application/vnd.api.v2+json |
import { createVersionRouter } from 'versionkit';
const router = createVersionRouter({
strategy: 'header',
headerName: 'Api-Version', // default
defaultVersion: '1',
versions: {
'1': {
deprecated: true,
deprecation: {
sunset: new Date('2026-06-01'),
deprecatedSince: new Date('2025-01-01'),
link: 'https://docs.example.com/changelog',
},
},
'2': {},
},
});
router
.handle('1', (req) => new Response(JSON.stringify({ version: 1 })))
.handle('2', (req) => new Response(JSON.stringify({ version: 2 })));
const handler = router.middleware();
// handler(request) => Promise<Response>
const router = createVersionRouter({
strategy: 'url',
versions: { '1': {}, '2': {} },
});
router
.handle('1', () => new Response('v1'))
.handle('2', () => new Response('v2'));
// GET /v2/users -> dispatches to version "2" handler
const router = createVersionRouter({
strategy: 'accept',
versions: { 'v1': {}, 'v2': {} },
});
router
.handle('v1', () => new Response('v1'))
.handle('v2', () => new Response('v2'));
// Accept: application/vnd.api.v2+json -> dispatches to "v2" handler
When a version has a sunset date, the response includes:
Sunset: Mon, 01 Jun 2026 00:00:00 GMT
When a link is provided, the response includes:
Link: <https://docs.example.com/changelog>; rel="deprecation"
When deprecatedSince is set:
Deprecation: @1735689600
When no date is specified but the version is deprecated:
Deprecation: true
import { Hono } from 'hono';
import { createVersionRouter } from 'versionkit';
const app = new Hono();
const router = createVersionRouter({ strategy: 'header', versions: { '1': {} } });
router.handle('1', (req) => new Response('v1'));
app.all('/api/*', (c) => router.middleware()(c.req.raw));
import express from 'express';
import { createVersionRouter } from 'versionkit';
const app = express();
const router = createVersionRouter({ strategy: 'header', versions: { '1': {} } });
router.handle('1', (req) => new Response('v1'));
const handler = router.middleware();
app.use('/api', async (req, res) => {
const webReq = new Request(`http://${req.headers.host}${req.url}`, {
method: req.method,
headers: req.headers as any,
});
const webRes = await handler(webReq);
res.status(webRes.status);
webRes.headers.forEach((v, k) => res.setHeader(k, v));
res.send(await webRes.text());
});
import Fastify from 'fastify';
import { createVersionRouter } from 'versionkit';
const fastify = Fastify();
const router = createVersionRouter({ strategy: 'url', versions: { '1': {} } });
router.handle('1', (req) => new Response('v1'));
const handler = router.middleware();
fastify.all('/v*', async (req, reply) => {
const webReq = new Request(`http://${req.hostname}${req.url}`, {
method: req.method,
headers: req.headers as any,
});
const webRes = await handler(webReq);
reply.status(webRes.status);
webRes.headers.forEach((v, k) => reply.header(k, v));
reply.send(await webRes.text());
});
createVersionRouter(opts: VersionRouterOptions): VersionRouterCreates a new version router.
VersionRouter.handle(version: string, handler: RequestHandler): thisRegisters a handler for a specific version. Chainable.
VersionRouter.middleware(): (req: Request) => Promise<Response>Returns a request handler that dispatches to the correct versioned handler.
VersionRouter.resolveVersion(req: Request): string | nullResolves which version applies to a given request without dispatching.
MIT
FAQs
Framework-agnostic API versioning with RFC 8594 Sunset and RFC 9745 Deprecation headers
The npm package versionkit receives a total of 3 weekly downloads. As such, versionkit popularity was classified as not popular.
We found that versionkit demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.

Security News
During a UK cyber test, a Mythos 5 agent used sockpuppets, social engineering, and prompt injection to try to get a maintainer to merge malware.