
Product
Microsoft Teams Notifications Are Now Available in Socket
Socket can now send alerts and supply chain attack notifications to Microsoft Teams, with filters that route the right updates to each channel.
x-openapi-flow
Advanced tools
Enforce, visualize and generate code from OpenAPI resource lifecycles — runtime guard, SDK gen, Postman/Insomnia/Redoc adapters, MCP sidecar for AI agents
🚀 2,100+ downloads in the first 3 weeks!
npx x-openapi-flow init --suggest-transitions
See your API lifecycle come alive from your OpenAPI spec, with one simple command
Validate, document, and generate flow-aware SDKs automatically.

openapi.json → describes your API
openapi.x.json → describes how to use it (flows)
x-openapi-flow adds a declarative state machine to your OpenAPI spec.
Model resource lifecycles, enforce valid transitions, and generate flow-aware artifacts for documentation, SDKs, and automation.
Define stateful workflows and lifecycle transitions directly inside your OpenAPI operations:
{
"operationId": "createOrder",
"x-openapi-flow": {
"version": "1.0",
"id": "create-order",
"current_state": "created",
"description": "Creates an order and starts the lifecycle",
"transitions": [
{
"transition_id": "order-created-to-paid",
"trigger_type": "synchronous",
"condition": "Payment is confirmed",
"decision_rule": "payOrder:response.200.body.payment_status == 'approved'",
"target_state": "paid",
"next_operation_id": "payOrder",
"operation_role": "mutate",
"prerequisite_operation_ids": ["createOrder"],
"evidence_refs": [
"payOrder:response.200.body.payment_status"
],
"propagated_field_refs": [
"createOrder:response.201.body.order_id"
],
"failure_paths": [
{
"reason": "Payment denied",
"target_state": "payment_failed",
"next_operation_id": "getOrder"
}
]
}
]
}
}
This flow defines an order lifecycle directly inside your OpenAPI:
created statepaid when payment is confirmedInstead of manually orchestrating API calls, the workflow is fully described alongside your API specification.
Building APIs is cheap. Building complex, multi-step APIs that teams actually use correctly is hard.
Teams face recurring problems:
x-openapi-flow exists to solve these pains: it makes lifecycles explicit, validates transitions automatically, and generates flow-aware docs and SDKs — so teams move faster, make fewer mistakes, and ship confident integrations.
Turn your OpenAPI spec into a single source of truth for API behavior:
Fastest way to see value (guided scaffold):
npx x-openapi-flow quickstart
cd x-openapi-flow-quickstart
npm install
npm start
Optional runtime:
npx x-openapi-flow quickstart --runtime fastify
Then run:
curl -s -X POST http://localhost:3110/orders
curl -i -X POST http://localhost:3110/orders/<id>/ship
Expected: 409 INVALID_STATE_TRANSITION.
Initialize flow support in your project:
npx x-openapi-flow init
# optional: infer suggested transitions using naming heuristics
npx x-openapi-flow init --suggest-transitions
After regenerating your OpenAPI file, apply and validate the flow (optional):
npx x-openapi-flow apply openapi.yaml --out openapi.flow.yaml
npx x-openapi-flow validate openapi.flow.yaml --profile strict --strict-quality
This will:
💡 Tip: run this in CI to enforce API workflow correctness
For larger APIs, you can define flow rules by resource (with shared transitions/defaults) and reduce duplication in sidecar files.
See: Sidecar Contract
Use the official reusable action to validate lifecycle rules in CI with a single step:
- name: Validate OpenAPI flow rules
uses: tiago-marques/x-openapi-flow/.github/actions/validate@main
with:
openapi-file: openapi.flow.yaml
profile: strict
strict-quality: "true"
Integration guide: GitHub-Actions-Integration.md
Here’s a real-world payment lifecycle represented in x-openapi-flow:
CREATED -> AUTHORIZED -> CAPTURED -> REFUNDED
Generate a visual graph of the lifecycle:
npx x-openapi-flow graph openapi.flow.yaml --format mermaid
Resulting diagram:
graph TD
CREATED --> AUTHORIZED
AUTHORIZED --> CAPTURED
CAPTURED --> REFUNDED
This visualization makes your API workflow explicit, easy to communicate, and ready for documentation or demos.
Create a TypeScript SDK that respects your API’s lifecycle and transition rules, following best practices seen in leading companies like Stripe and Adyen:
npx x-openapi-flow generate-sdk openapi.flow.yaml --lang typescript --output ./sdk
Example usage:
const payment = await sdk.payments.create({ amount: 1000 });
await payment.authorize();
await payment.capture();
This SDK guides developers through valid transition paths, following patterns used by market leaders to ensure safe and intuitive integrations.
CI validation is important, but production safety needs request-time enforcement.
x-openapi-flow now includes an official runtime guard for Node.js that can block invalid state transitions during request handling.
operationId (when available) or by method + route409 error payloadsInstall and use directly in your API server:
const {
createExpressFlowGuard,
createFastifyFlowGuard,
} = require("x-openapi-flow/lib/runtime-guard");
Express example:
const express = require("express");
const { createExpressFlowGuard } = require("x-openapi-flow/lib/runtime-guard");
const openapi = require("./openapi.flow.json");
const app = express();
app.use(
createExpressFlowGuard({
openapi,
async getCurrentState({ resourceId }) {
if (!resourceId) return null;
return paymentStore.getState(resourceId); // your DB/service lookup
},
resolveResourceId: ({ params }) => params.id || null,
})
);
Fastify example:
const fastify = require("fastify")();
const { createFastifyFlowGuard } = require("x-openapi-flow/lib/runtime-guard");
const openapi = require("./openapi.flow.json");
fastify.addHook(
"preHandler",
createFastifyFlowGuard({
openapi,
async getCurrentState({ resourceId }) {
if (!resourceId) return null;
return paymentStore.getState(resourceId);
},
resolveResourceId: ({ params }) => params.id || null,
})
);
Error payload for blocked transition:
{
"error": {
"code": "INVALID_STATE_TRANSITION",
"message": "Blocked invalid transition for operation 'capturePayment'. Current state 'CREATED' cannot transition to this operation.",
"operation_id": "capturePayment",
"current_state": "CREATED",
"allowed_from_states": ["AUTHORIZED"],
"resource_id": "pay_123"
}
}
More details: Runtime Guard
No need to write your own getCurrentState from scratch. x-openapi-flow ships four ready-made adapters:
const {
MemoryAdapter, // in-process Map — ideal for tests and single-instance dev
FileAdapter, // JSON file on disk — great for demos and local servers
RedisAdapter, // ioredis-backed — production-ready, requires: npm install ioredis
GenericSQLAdapter, // any SQL DB (pg, mysql2, knex…) via query callback
} = require("x-openapi-flow/lib/runtime-guard");
// in-memory (testing / local)
const store = new MemoryAdapter();
app.use(createExpressFlowGuard({ openapi, ...store.forGuard() }));
// persist every transition to Redis
const Redis = require("ioredis");
const redisStore = new RedisAdapter({ client: new Redis(), prefix: "orders:" });
app.use(createExpressFlowGuard({ openapi, ...redisStore.forGuard() }));
// call setState after each successful request to keep the state in sync
app.post("/orders/:id/pay", async (req, res) => {
await redisStore.setState({ resourceId: req.params.id, state: "paid" });
res.json({ ok: true });
});
GenericSQLAdapter example with pg:
const { Pool } = require("pg");
const pool = new Pool();
const sqlStore = new GenericSQLAdapter({
query: (sql, params) => pool.query(sql, params).then(r => r.rows),
dialect: "pg",
});
await sqlStore.ensureTable(); // CREATE TABLE IF NOT EXISTS xflow_state (…)
app.use(createExpressFlowGuard({ openapi, ...sqlStore.forGuard() }));
All adapters implement getCurrentState, setState, deleteState and forGuard() — a convenience method that returns the exact shape expected by the guard options.
Want to see the value immediately? Use the official minimal demo:
Run in under 5 minutes:
cd example/runtime-guard/minimal-order
npm install
npm start
Create an order, then try to ship before payment (must return 409 INVALID_STATE_TRANSITION):
curl -s -X POST http://localhost:3110/orders
curl -i -X POST http://localhost:3110/orders/<id>/ship
HTTPie equivalent:
http POST :3110/orders
http -v POST :3110/orders/<id>/ship
Use a reusable deterministic engine independently of CLI and OpenAPI parsing:
const { createStateMachineEngine } = require("x-openapi-flow/lib/state-machine-engine");
const engine = createStateMachineEngine({
transitions: [
{ from: "CREATED", action: "confirm", to: "CONFIRMED" },
{ from: "CONFIRMED", action: "ship", to: "SHIPPED" },
],
});
engine.canTransition("CREATED", "confirm");
engine.getNextState("CREATED", "confirm");
engine.validateFlow({ startState: "CREATED", actions: ["confirm", "ship"] });
More details: State Machine Engine
Convert x-openapi-flow metadata to a pure engine definition:
const { createStateMachineAdapterModel } = require("x-openapi-flow/lib/openapi-state-machine-adapter");
const { createStateMachineEngine } = require("x-openapi-flow/lib/state-machine-engine");
const model = createStateMachineAdapterModel({ openapiPath: "./openapi.flow.yaml" });
const engine = createStateMachineEngine(model.definition);
More details: OpenAPI State Machine Adapter
x-openapi-flow is ideal for teams and organizations that want clear, enforceable API workflows:
See how x-openapi-flow extends OpenAPI to make your API workflows explicit, enforceable, and actionable:
| Capability | OpenAPI | x-openapi-flow |
|---|---|---|
| Endpoint contracts | ✅ Yes | ✅ Yes (fully compatible, extended) |
| Lifecycle states | ❌ No | ✅ Yes – define states for each resource |
| Transition validation | ❌ No | ✅ Yes – catch invalid calls before runtime |
| Flow diagrams | ❌ No | ✅ Yes – generate visual lifecycle graphs |
| Usage guidance (next valid actions) | Limited/manual | ✅ Built-in via lifecycle metadata – guides developers and AI agents |
| Dimension | x-openapi-flow | OpenAPI Workflows (Arazzo) | AsyncAPI |
|---|---|---|---|
| Primary focus | Resource lifecycle states & runtime enforcement | Multi-step API workflows (orchestration scripts) | Event-driven / async messaging APIs |
| Lifecycle states | ✅ Explicit states per resource | ❌ No state model | ❌ No state model |
| Runtime enforcement | ✅ Express/Fastify middleware (409 on invalid transitions) | ❌ Spec-only, no runtime guard | ❌ Spec-only |
| SDK generation | ✅ TypeScript, Kotlin, Python, Go | ❌ No codegen | Limited |
| Postman / Insomnia export | ✅ Built-in adapters | ❌ No | ❌ No |
| AI agent support | ✅ MCP sidecar + structured sidecar contract | ❌ No | ❌ No |
| Breaking change detection | ✅ diff --breaking-only --fail-on-breaking | ❌ No | ❌ No |
| CI validation | ✅ CLI + GitHub Action | ❌ No official CLI | Limited |
| OpenAPI compatibility | ✅ Sidecar extends existing specs | Separate Arazzo spec | Separate AsyncAPI spec |
In short: use x-openapi-flow when you need enforceable, stateful API lifecycles that go beyond documentation into runtime safety, SDK generation, and AI-ready contracts. Use Arazzo for scripting multi-step HTTP journeys. Use AsyncAPI for documenting event/message-driven systems.
Explore how x-openapi-flow integrates with popular API tools, making lifecycles and flows explicit for documentation and testing.
cd example/swagger-ui
npm install
npm run apply
npm start

Lifecycle panel shows valid states and transitions

Detailed view of transitions per operation
cd example/redoc
npm install
npm run apply
npm run generate

Auto-generated lifecycle diagrams make documentation clear and consistent
cd example/postman
npm install
npm run apply
npm run generate

Collections reflect lifecycle order, reducing integration errors
cd example/insomnia
npm install
npm run apply
npm run generate

Requests are pre-organized according to lifecycle transitions
Use x-openapi-flow from the command line to manage, validate, visualize, and generate SDKs/docs for your API workflows.
npx x-openapi-flow help [command] # show help for a specific command
npx x-openapi-flow --help # general help
npx x-openapi-flow version # show version
npx x-openapi-flow doctor [--config path] # check setup and config
npx x-openapi-flow completion [bash|zsh] # enable shell autocompletion
npx x-openapi-flow quickstart [--dir path] [--runtime express|fastify] [--force] # scaffold runnable onboarding project
# initialize flow support
npx x-openapi-flow init [--flows path] [--force] [--dry-run]
# apply flows to OpenAPI
npx x-openapi-flow apply [openapi-file] [--flows path] [--out path]
# validate transitions
npx x-openapi-flow validate <openapi-file> [--profile core|relaxed|strict] [--strict-quality] [--semantic]
# preview sidecar changes
npx x-openapi-flow diff [openapi-file] [--format pretty|json]
# detect breaking flow changes (use in CI to fail PRs)
npx x-openapi-flow diff [openapi-file] --breaking-only --fail-on-breaking
# generate lifecycle diagrams
npx x-openapi-flow graph [openapi-file] [--format mermaid|json]
# generate Redoc docs
npx x-openapi-flow generate-redoc [openapi-file] [--output path]
# export flows
npx x-openapi-flow export-doc-flows [openapi-file] [--output path] [--format markdown|json]
# generate flow-aware SDK
npx x-openapi-flow generate-sdk [openapi-file] --lang typescript [--output path]
# generate executable flow tests (happy path + invalid transitions)
npx x-openapi-flow generate-flow-tests [openapi-file] [--format jest|vitest|postman] [--output path]
# postman/newman-oriented collection with flow scripts
npx x-openapi-flow generate-flow-tests [openapi-file] --format postman [--output path] [--with-scripts]
Full details:
Use x-openapi-flow runtime guard inside NestJS via a custom guard or interceptor. No dedicated package required:
// flow-guard.middleware.ts
import { Injectable, NestMiddleware } from "@nestjs/common";
import { createExpressFlowGuard, MemoryAdapter } from "x-openapi-flow/lib/runtime-guard";
import openapi from "./openapi.flow.json";
const store = new MemoryAdapter(); // swap for RedisAdapter or GenericSQLAdapter in production
const guard = createExpressFlowGuard({ openapi, ...store.forGuard() });
@Injectable()
export class FlowGuardMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
guard(req, res, next);
}
}
// app.module.ts — apply to specific routes
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(FlowGuardMiddleware).forRoutes("orders");
}
}
After each successful state-changing request, call store.setState to advance the resource:
@Post(":id/pay")
async pay(@Param("id") id: string) {
// … business logic …
await store.setState({ resourceId: id, state: "paid" });
return { ok: true };
}
Get the most out of x-openapi-flow with detailed guides, examples, and integration instructions:
Adoption Guide – docs/wiki/getting-started/Adoption-Playbook.md
Learn how to introduce x-openapi-flow into your API workflow efficiently
Troubleshooting – docs/wiki/reference/Troubleshooting.md
Quick solutions to common issues and validation errors
Real Examples – docs/wiki/engineering/Real-Examples.md
Explore real OpenAPI specs enhanced with lifecycle metadata
Integrations:
We’re actively expanding x-openapi-flow to support multiple platforms and SDKs. Check our progress:
🗂 Roadmap Overview – #2
See planned features and high-level goals
🐍 Python SDK MVP – #3
Enable Python developers to use flow-aware SDKs
🏎 Go SDK MVP – #4
Bring lifecycle-aware SDKs to Go projects
☕ Kotlin SDK MVP – #5
Support Android and JVM developers with flow-aware SDKs
Keep track of updates and improvements in x-openapi-flow:
Latest Version (v1.7.0) – CHANGELOG.md#170---2026-04-02
See what shipped in the current release
Version History – CHANGELOG.md
Review the full version history and past updates
Release Notes – GitHub Release v1.7.0
See detailed notes for the latest release, including new features and fixes
To ensure clarity and accessibility for the global developer community, all project documentation should be written in English. This helps contributors, users, and AI agents understand and use x-openapi-flow consistently.
FAQs
Enforce, visualize and generate code from OpenAPI resource lifecycles — runtime guard, SDK gen, Postman/Insomnia/Redoc adapters, MCP sidecar for AI agents
The npm package x-openapi-flow receives a total of 71 weekly downloads. As such, x-openapi-flow popularity was classified as not popular.
We found that x-openapi-flow 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.

Product
Socket can now send alerts and supply chain attack notifications to Microsoft Teams, with filters that route the right updates to each channel.

Security News
pnpm 12 rewrites the package manager in Rust, cutting install times by up to 90% while preserving pnpm 11 workflows and lockfiles.

Security News
Socket CTO Ahmad Nassri joins AppSec leaders at Black Hat to discuss active malware, package manager risks, and software supply chain defense.