Build, test and simulate complex API workflows in a node-based visual editor.
Chain API calls as connected nodes, pipe any node's response into a later request, and watch the whole flow run step by step.
Think Postman meets a flow builder: Create Customer → Share KYC → Create Payout becomes three wired nodes, and Create Payout reads {{nodes.Create Customer.response.body.id}} straight from the earlier call.
- Visual flow builder — each node is one API request (method, URL, headers, body). Drag to connect any node to any other; the target becomes a child, one level down. Delete a node and the graph re-levels itself.
- Parallel runs — nodes on the same level execute concurrently; a failure marks everything downstream as skipped instead of aborting the run. All green earns confetti.
- Response chaining —
{{env.API_KEY}}and{{nodes.<name>.response.body.…}}templates in URLs, headers and bodies, with a variable picker fed by real responses. - Import anything — paste a cURL command, or drop an OpenAPI 3, Swagger 2 or Postman collection; every endpoint becomes a node. An arrange step lets you set each request's level and drop the ones you don't want before building.
- Workflow-wide env & headers — pick one active environment and one header set from the top bar; both apply to every node. Inline node headers override the set.
- Pre-request scripts — a Postman-style script (with
pm+CryptoJS) runs before each request; toggle it per workflow. - JSON body editor — syntax-highlighted, with
{{template}}awareness. - Server-side proxy — requests execute from the server, so browser CORS never gets in the way.
- Accounts & persistence — email OTP sign-in (+ optional Google / GitHub) via Better Auth; everything saves per user in Postgres.
- Export / import — share a workflow with its referenced bodies and header sets as JSON.
- Private beta mode — set one passcode and the whole app hides behind a waitlist page; invited testers enter the code, everyone else can join the list.
cp .env.example .env # fill in the required keys (see below)
npm install
npx drizzle-kit push # create the database tables
npm run dev # http://localhost:3000Sign in with any email — without RESEND_API_KEY set, the OTP code is printed to the server console. A demo workflow targeting the built-in /api/echo endpoint is seeded on first sign-in.
- Nodes & levels — a node's level is its row on the canvas. Level 1 runs after Start; level 2 after level 1, and so on. Connecting or dragging a node re-derives its level and re-lays out the graph.
- Templating —
{{env.KEY}}pulls from the active environment;{{nodes.<label>.response.body.path.to.value}}pulls from an upstream node's last response. Resolved at run time. - Resources — request bodies, header sets and environments are saved once and referenced across nodes and workflows.
- Execution — the runner walks the graph level by level, fires each level's nodes in parallel through
/api/execute(the server proxy), and feeds responses back into the template context for downstream nodes. A failed node marks its descendants skipped; the rest of the flow keeps running.
All variables live in .env (never commit it — only .env.example is tracked); a few extra niche keys are documented inline in .env.example.
Postgres connection string in the form postgresql://USER:PASSWORD@HOST:PORT/DATABASE. Get one from any of:
-
Local Docker (quickest for development):
docker run -d --name orqly-pg \ -e POSTGRES_PASSWORD=pg -e POSTGRES_DB=orqly \ -p 5432:5432 postgres:16
then use
postgresql://postgres:pg@localhost:5432/orqly. -
Locally installed Postgres — create a database (
createdb orqly) and use your local credentials. -
Hosted Postgres — create a free project on Neon, Supabase or Railway; each shows a ready-made
postgresql://…URL. If the provider requires TLS, append?sslmode=require.
After setting it, run npx drizzle-kit push once to create the tables.
Random secret used to sign sessions. Generate it yourself:
npx @better-auth/cli@latest secret # or: openssl rand -hex 32Use a different secret per environment; rotating it signs every user out.
The URL the app is served from, no trailing slash. Local: http://localhost:3000. Production: your deployed origin.
Delivers sign-in OTP codes by email via Resend. Unset, codes are printed to the server console (dev only). RESEND_FROM needs a domain verified in Resend.
Set to put the whole app behind the waitlist: every page and API redirects to /waitlist until the visitor enters this passcode (share it with beta testers). Unset = the app is open (local dev, self-hosting). NEXT_PUBLIC_DISCORD_URL / NEXT_PUBLIC_X_URL add social links to the waitlist success screen.
Enables "Continue with Google" (hidden while unset; email/password works without them). From the Google Cloud Console:
- Create/select a project at console.cloud.google.com.
- APIs & Services → OAuth consent screen: External, add yourself as a test user.
- Credentials → Create credentials → OAuth client ID → Web application:
- Authorized origin:
http://localhost:3000(+ your production origin) - Redirect URI:
http://localhost:3000/api/auth/callback/google(+ production)
- Authorized origin:
- Copy the Client ID and secret into
.env, then restart the dev server.
Enables "Continue with GitHub". Create an OAuth App at github.com/settings/developers with redirect URI {BETTER_AUTH_URL}/api/auth/callback/github.
Set to 1 to make the request proxy (/api/execute) refuse URLs pointing at loopback/private addresses (localhost, 10.x, 192.168.x, …), so users can't probe your internal network. Leave unset in local dev — the seeded demo calls the app's own /api/echo, which a private-IP block would reject.
Next.js (App Router) · TypeScript · Tailwind CSS · React Flow (@xyflow/react) · zustand · Better Auth · Drizzle ORM · Postgres
src/
app/ Next.js routes — pages, auth, /api/execute proxy, /api/data CRUD
components/ canvas (React Flow nodes), sidebar, inspector, wizard, shared UI
lib/ store (zustand), runner, interpolation, importers (curl/openapi/postman)
db/ Drizzle schema
Issues and PRs welcome.
npm run lint # eslint
npx tsc --noEmit # type-checkKeep changes minimal and typed; npx drizzle-kit push after any schema change. Open an issue first for larger features.
MIT © Chakravarti Avinit