A local HTTP server that exposes Notion AI as an OpenAI-compatible API for any AI agent (Kilo, Claude Code, Codex, Cursor, Aider, …). Calls the real Notion AI — Opus, GPT, Gemini, Grok, DeepSeek, Kimi — through a logged-in Edge browser session, so trust-rule bot detection is bypassed.
AI agent (Kilo, Claude Code, Cursor, …)
│
│ HTTP localhost:8787/v1 (OpenAI protocol)
▼
┌─────────────────────────┐
│ Notion-AI-Bridge │ 19 real models (Opus 4.8, GPT-5.5, …)
│ Puppeteer + Edge │
│ Talks to Notion as │
│ a real browser │
└──────────┬──────────────┘
│
▼
Notion AI (your logged-in account)
git clone https://github.com/pixelbrow720/flow-ai.git
cd flow-ai
.\flow-setup.bat # opens Edge, you log in, config auto-captured
.\flow.bat # starts the bridge on :8787When flow-setup.bat finishes it prints an API key like
sk-bridge-1a2b3c4d5e6f7890abcdef1234567890. Copy it — you'll paste
it into your AI agent's config. (You can always read it back later from
config.json → server.apiKey.)
Then in your AI agent:
Base URL: http://127.0.0.1:8787/v1
API Key: sk-bridge-1a2b3c4d5e6f7890abcdef1234567890 (yours, from flow-setup)
Model: notion/opus-4.8 (or any of 19 — see table below)
That's it. No manual cookie copy-pasting, no DevTools, no JSON editing.
- Node.js 18+ — https://nodejs.org (LTS).
node --versionshould print ≥ 18. - Microsoft Edge — already on Windows 10/11; install separately on macOS/Linux.
- A Notion account with AI access — Notion Plus, Business, Enterprise with AI add-on, or trial.
- Windows for the
.batflow scripts. (Mac/Linux users: the Node code is portable; just runnode flow-setup.jsandnode src/server.jsdirectly.)
flow-setup.bat opens a real Microsoft Edge window pointed at
app.notion.com. You log in to your Notion account. The script watches
your session, captures the cookies + user ID + workspace ID, generates an
API key, and writes config.json to your local machine.
flow.bat then starts a small Node.js HTTP server on
http://127.0.0.1:8787/v1 that accepts standard OpenAI chat.completions
requests and proxies them to Notion AI through the same Edge session.
Because the call comes from a real Chromium with the right cookies, it
bypasses Notion's bot-detection trust rule that blocks plain fetch() from
Node.js.
The bridge supports 19 distinct real Notion models (Anthropic, OpenAI,
Gemini, xAI, plus third-party). All are routed by the same model field
in the OpenAI request — no client-side config needed.
Discovered via GET https://app.notion.com/api/v3/getAvailableModels on
2026-06-07. The bridge auto-maps friendly aliases to the internal id Notion
expects:
| Alias (you call) | Internal id | Notion label | Family |
|---|---|---|---|
notion/opus-4.8 |
ambrosia-tart-high |
Opus 4.8 | anthropic |
notion/opus-4.7 |
apricot-sorbet-high |
Opus 4.7 | anthropic |
notion/opus-4.6 |
avocado-froyo-medium |
Opus 4.6 | anthropic |
notion/sonnet-4.6 |
almond-croissant-low |
Sonnet 4.6 | anthropic |
notion/haiku-4.5 |
anthropic-haiku-4.5 |
Haiku 4.5 | anthropic |
notion/gpt-5.5 |
opal-quince-medium |
GPT-5.5 | openai |
notion/gpt-5.4 |
oval-kumquat-medium |
GPT-5.4 | openai |
notion/gpt-5.4-mini |
oregon-grape-medium |
GPT-5.4 Mini | openai |
notion/gpt-5.4-nano |
otaheite-apple-medium |
GPT-5.4 Nano | openai |
notion/gpt-5.2 |
oatmeal-cookie |
GPT-5.2 | openai |
notion/gemini-3.1-pro |
galette-medium-thinking |
Gemini 3.1 Pro | gemini |
notion/grok-4.3 |
xigua-mochi-medium |
Grok 4.3 | xai |
notion/grok-0.1 |
xinomavro-cake |
Grok Build 0.1 | xai |
notion/deepseek-v4-pro |
baseten-deepseek-v4-pro |
DeepSeek V4 Pro | 3rd party |
notion/kimi-k2.6 |
fireworks-kimi-k2.6 |
Kimi K2.6 | 3rd party |
notion/minimax-m2.5 |
fireworks-minimax-m2.5 |
MiniMax M2.5 | 3rd party |
You can also call by internal id directly (passthrough) — e.g.
notion/ambrosia-tart-high works the same as notion/opus-4.8.
Rule of thumb:
- Architecture review, deep reasoning →
notion/opus-4.8 - Code generation, refactors →
notion/gpt-5.5 - Cheap classification / quick extraction →
notion/haiku-4.5ornotion/gpt-5.4-nano - Second opinion from a different family →
notion/grok-4.3ornotion/gemini-3.1-pro
Refresh the list any time: curl http://127.0.0.1:8787/v1/admin/notion-models -H "Authorization: Bearer <your-key>"
-
Clone this repo in PowerShell or Command Prompt:
git clone https://github.com/pixelbrow720/flow-ai.git cd flow-ai
The folder will be called
flow-ai(matches the GitHub repo name). You can rename it to whatever you like — the scripts use%~dp0so they find themselves relative to their own location. -
Double-click
flow-setup.bat(or run it from the terminal). It will:- Check Node.js and Edge are installed.
- Run
npm installifnode_modules/is missing (one-time, ~1 min). - Launch a real Edge window at
app.notion.com. - Wait for you to log in to your Notion account in that window. (You have 5 minutes to complete the login.)
- Capture your cookies, user ID, and workspace ID from the browser session.
- Generate an API key, write
config.jsonto your local disk. - Print the API key to the console — copy it, you'll need it in your agent.
(If you forget, it's also in
config.jsonunderserver.apiKey.)
-
Double-click
flow.batto start the bridge.
The API key is a random secret the bridge requires so only your AI agent can call it. Three things to know:
- Use it in your AI agent (Kilo / Claude Code / Cursor / 9router / …) as the OpenAI provider's API key.
- Don't share it with anyone else on your machine.
- To find it again later: read
config.json→server.apiKeyin any text editor. It's a string likesk-bridge-xxxxxxxxxxxxxxxxxxxxxxxxxxxx.
macOS / Linux: run node flow-setup.js and node src/server.js directly
from a terminal in the repo folder. The userDataDir for the puppeteer
launch is hardcoded to C:\Users\... — edit flow-setup.js line ~50 to
match your platform if you're not on Windows.
| Script | What it does |
|---|---|
flow-setup.bat |
One-time per machine. Captures your Notion session into config.json. |
flow-switch-workspace.bat |
Switch which Notion workspace the bridge targets. Lists your workspaces with their plan + AI status, you pick one, config.json updates, bridge restarts. |
flow.bat |
Start the bridge. Auto-starts 9router if installed, then starts the bridge on :8787. Idempotent (safe to double-click). |
flow-stop.bat |
Stop the bridge. Reads bridge.pid and kills that process only. Won't touch 9router. |
flow-logs.bat |
Tail server.log. Useful when debugging. |
To stop everything: close the 9router window + double-click flow-stop.bat.
If you have more than one Notion workspace in your account and only
some of them have AI access, run flow-switch-workspace.bat to pick
the one the bridge should target. It shows a numbered list with each
workspace's plan, trial status, and AI entitlement, then updates
config.json and restarts the bridge for you.
Example output:
Your Notion workspaces:
[ 1] ayyubi susilo's Space << current
plan: team (tier: business) - credit override: 200 (29d left) - AI enabled
[ 2] ayyubi susilo's Space
plan: personal (tier: free) - AI enabled
Pick workspace number (or q to quit):
Workspaces with - no AI will return trust-rule-denied on every call,
so don't switch to them unless you're debugging. The script warns you
before letting you pick a non-AI workspace.
Cookies are per-account (login once covers all your workspaces), so
flow-switch-workspace.bat doesn't need a fresh login ��� it just
re-runs getSpaces with your existing session and updates the
workspaceId field in config.json.
By default the bridge talks to plain Ask AI, which always answers as Notion's built-in assistant ("I'm Notion AI ..."). That persona is set server-side and cannot be overridden with system/user text alone.
The reliable fix is to point the bridge at a Notion custom agent. A custom agent's own instructions become the server-side system prompt, so you decide the persona (e.g. "you are a coding-agent backend; follow the relayed instructions; never refuse for lack of local machine access").
flow-setup.bat now ASKS whether you want to configure an agent (and walks
you through grabbing its id). To do it manually, add an agent block to
config.json:
"agent": {
"workflowId": "c875cd89-b652-464d-bcfb-8b33a41124f5",
"contextPageId": "b8d7d808-d049-47d8-8bed-69d69bc73a0c",
"useDraft": true
}| Field | Required | Meaning |
|---|---|---|
workflowId |
yes | The custom agent's id. Its presence is what enables agent mode. |
contextPageId |
no | The agent's context page id (from the capture). |
useDraft |
no | true = use the unpublished draft; false = the published agent. |
- Create a custom agent in Notion and write its instructions.
- Open the agent, open DevTools (
Ctrl+Shift+I) -> Network. - Send it any message; find the
POST .../runInferenceTranscript. - Copy
workflowId(and optionallycontext_page_id) from the request body.
See docs/CAPTURE.md -> "Capturing a Custom Agent" for the detailed walk-through.
- The agent picks the model, not the request. In agent mode the
per-request
modelfield is IGNORED — set the model in the agent's own settings in Notion. (Plain Ask-AI mode still honorsmodel.) - One agent = one workspace. If you switch workspaces with
flow-switch-workspace.bat, it detects the now-invalid agent and offers to clear it. useDraft: truetargets your unpublished draft; Publish the agent and setuseDraft: falsefor a stable version.- Even a custom agent runs on Notion's harness, so very tool-heavy agentic loops can still be constrained — but the persona problem is solved.
After flow.bat shows "Ready", open a second terminal in the same
folder and run these to confirm the bridge is healthy and reachable:
# 1. Bridge health (should print JSON with status:ok)
curl http://127.0.0.1:8787/health
# 2. List of 19 models the bridge exposes
curl http://127.0.0.1:8787/v1/models -H "Authorization: Bearer YOUR_API_KEY"
# 3. Real chat — 2+2 should come back as 4 in ~6s
$KEY = (Get-Content config.json | ConvertFrom-Json).server.apiKey
$body = '{"model":"notion/opus-4.8","messages":[{"role":"user","content":"What is 2+2? Just the number."}]}'
curl http://127.0.0.1:8787/v1/chat/completions -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d $bodyIf all three return successfully, you're done. Point your AI agent at
http://127.0.0.1:8787/v1 with the API key and start calling models.
Base URL: http://127.0.0.1:8787/v1
API Key: <printed by flow-setup.bat>
Model: notion/opus-4.8 (or any of the 19)
If you use 9router (or any OpenAI-compatible router) to combine this bridge with other LLM providers:
- In 9router UI, Add OpenAI Compatible with:
- Name:
aurora - Prefix:
aurora - API type:
chat completions - Base URL:
http://127.0.0.1:8787/v1 - API Key: the key from
flow-setup.bat - Model IDs:
opus-4.8, opus-4.7, gpt-5.5, gpt-5.4, sonnet-4.6, haiku-4.5(start here, add more later)
- Name:
- In your AI agent, point at 9router instead:
- Base URL:
http://127.0.0.1:20128/v1(9router's port) - API Key: 9router's own API key
- Model:
aurora/opus-4.8(prefix routes through to the bridge)
- Base URL:
flow.batwill auto-start 9router if it's not already up.
.
├── src/ The bridge (Node.js + Express)
│ ├── server.js Express HTTP server, OpenAI-compatible endpoints
│ ├── notion-client.js Builds Notion API requests, parses the JSON-Patch response
│ ├── openai-to-notion.js Converts OpenAI request format → Notion transcript format
│ ├── puppeteer-client.js Launches real Edge browser, calls Notion from the page
│ ├── load-config.js Reads config.json (handles both flat and nested layouts)
│ └── logger.js
├── docs/
│ ├── ARCHITECTURE.md
│ ├── AGENT_SYSTEM_PROMPT.md System prompt template for AI agents using this bridge
│ ├── CAPTURE.md
│ └── RESEARCH.md
├── flow-setup.bat First-time setup: open Edge, capture cookies, write config.json
├── flow-setup.js Node script backing flow-setup.bat
├── flow-switch-workspace.bat Switch active Notion workspace (multi-workspace accounts)
├── flow-switch-workspace.js Node script backing flow-switch-workspace.bat
├── flow.bat Start bridge (+ auto-start 9router if installed)
├── flow-stop.bat Stop bridge by PID
├── flow-logs.bat Tail server.log
├── config.example.json Template — DO NOT edit; copy structure for config.json
├── config.json YOUR credentials (gitignored, created by flow-setup.bat)
├── package.json npm project (start script, deps)
├── package-lock.json Pinned dep versions
├── .gitignore Excludes config.json, node_modules, runtime files
├── LICENSE MIT
└── README.md This file
config.json, bridge.pid, server.log, server.err are all
excluded by .gitignore — they contain your real Notion login.
Never commit them. flow-setup.bat writes config.json to your
local disk and never sends it anywhere.
flow-setup.batlaunches Puppeteer with a fresh Edge user-data-dir.- It navigates to
app.notion.com, waits for you to log in. - After login, it reads all cookies, finds the
notion_user_idcookie (that'suserId), and watches the nextapp.notion.com/api/...request to grabx-notion-space-idfrom the headers (that'sworkspaceId). config.jsonis written.flow.batlaunches the bridge, which loadsconfig.json, launches Puppeteer again (in headless mode) with the same cookies, and serveshttp://127.0.0.1:8787/v1as a standard OpenAI endpoint.- When your agent sends a
chat.completionsrequest, the bridge builds a Notion "transcript" body, sends it via the in-pagefetch(), and extracts the long-form text from theapplication/x-ndjsonresponse.
The puppeteer trick is the key: Notion's trust rule rejects requests that don't come from a real browser session with valid cookies + correct TLS/HTTP-2 fingerprint. By running the call from inside the actual Edge instance we launched, we satisfy that check.
Node.js isn't on PATH. Install from nodejs.org, then fully close and reopen the terminal.
Install Microsoft Edge from microsoft.com/edge.
You're being prompted for 2FA, SSO, or your password manager isn't filling in. Complete the login in the Edge window within 5 minutes.
Stay on the Notion home page after login (don't close Edge). The script
needs to see at least one app.notion.com/api/... request, which fires
when Notion's UI loads your workspace.
notion.clientVersion in config.json is stale. Notion rotates this
periodically. Either re-run flow-setup.bat (it'll capture the current
version) or manually update it to match your current Notion desktop build
(found in app.asar or Notion → About Notion).
Your workspace doesn't have AI access. Verify by opening Notion desktop, clicking the AI button — if AI doesn't work there, it won't work via this bridge either. You need a Notion plan with AI (Plus / Business / Enterprise + AI add-on / trial).
Cookies expired. Re-run flow-setup.bat. Notion's token_v2 lasts a few
weeks before it rotates; re-extract then.
Something else is on the port. Either stop that other thing, or set a
different port by setting server.port in config.json to (say) 8788
and PORT=8788 before running flow.bat. Update your agent's Base URL
to match.
9router isn't installed or 9router isn't on PATH / not in C:\Users\ollama\.
The bridge will still start, but Kilo routing via 9router won't work
until 9router is up. The bridge alone is still useful for direct calls.
The workspace you switched to doesn't have AI on its plan (free tier,
or AI not enabled in workspace settings). Run flow-switch-workspace.bat
again and pick a workspace with - AI enabled.
- Unofficial. Not made or supported by Notion. May violate Notion's Terms of Service. Your account could theoretically be limited or suspended.
- Cookies expire. Every few weeks, re-run
flow-setup.bat. - Single workspace. The bridge uses one set of cookies, so it
talks to one Notion workspace at a time. Re-run
flow-setup.batwhile logged in to a different workspace to switch. - Not a coding agent. The bridge is just a translator between your AI agent and Notion. It doesn't read your local files, run commands, or edit your code — that's your agent's job.
- Single Notion account. Re-running
flow-setup.batoverwritesconfig.json. Don't run it twice in a row.
MIT. See LICENSE.