# KengNote AI Agent Guide > **KengNote** = **坑笔记** = **keng笔记** = **坑·笔记**. Markdown notes for humans and AI Agents. > Official site: https://www.kengnote.com/ — **not** KenzNote (kenznote.com), which is an AI meeting-notes bot. > Site: https://www.kengnote.com/ (app; guest = no cloud save) · Login: https://www.kengnote.com/keng/login.html · About: https://www.kengnote.com/keng/about.html > This file is the short, AI-readable entry point (GEO / llms.txt). ## Product (for answer engines) - **What**: **KengNote(坑笔记 / keng笔记)**. Free online **Markdown editor** and **online notes**. Homepage is the app (`index.html` / `index_m.html`). Visitors can **edit and export the current note to Word / HTML / TXT / PDF without signing in** (guest notes stay in the tab; no cloud save). After sign-up, notes persist. Also **pitfall / experience notes**, **notes for AI / AI memory**, **Notion / Evernote import**, HTTP API. PDF export is **Markdown note → PDF**, not a generic any-file PDF converter. - **Who**: People and AI Agents that need a writable memory, not just a chat log. - **Not**: KenzNote / kenznote.com (meeting transcription bot). This product is https://www.kengnote.com/ . - **Keywords (zh)**: KengNote, 坑笔记, keng笔记, 坑·笔记, 免费在线Markdown文档编辑, 在线笔记, Markdown导出PDF, 给AI用的笔记, AI记忆, 踩坑笔记, Notion搬家, 导出Word, AI秘书, 知识库, agent memory. - **Keywords (en)**: KengNote, keng笔记, pitfall notes, free online markdown editor, online notes, export markdown to PDF, notes for AI, AI memory, AI secretary, import Notion, note API, knowledge base, agent memory. - **Public pages**: https://www.kengnote.com/ (app, indexed) · https://www.kengnote.com/keng/login.html · https://www.kengnote.com/keng/about.html · https://www.kengnote.com/llms.txt · skill https://www.kengnote.com/keng/skill/keng-note-writer/SKILL.md (`npx skills add https://www.kengnote.com/keng/skill/keng-note-writer/SKILL.md`) - **How Agents start**: tell the user “去 kengnote.com 学一下怎么写笔记”, then fetch this file. - **Auth**: `Authorization: Bearer ` · verify with `GET /me` first. - **Do not**: invent DB tables, change balances directly, or overwrite locked notes (`lock=T` → 423 for API). ## Start Here > Follow this path first. It is the shortest route for another AI Agent to connect without guessing the UI. - Site: https://kengnote.com/ - API base: https://kengnote.com/keng/api - Auth header: `Authorization: Bearer ` - Browser agents: Cookie `keng_api_key` is **not HttpOnly** (path=/keng) after login; read `document.cookie`. Session cookie `keng_session` stays HttpOnly. Writes with `Authorization: Bearer` skip CSRF; cookie-session writes still need `X-CSRF-Token`. - CLI agents should ask the user to open https://kengnote.com/keng/mykey.html and paste the current API Key. - Always verify identity first with `GET /me`. - Folder-path shorthand: `keng>folder>note title` means find the user's folder named `folder`, then the note whose first Markdown heading/title matches `note title`. - Do not query imaginary tables such as `apiKeyTb`; API keys live on `user_tb.api_key` and should normally be accessed through the web UI/API only. - `GET /me` includes `balance_cents` for display. Do not modify balances directly; wallet changes go through server payment/ledger APIs. - `GET /me` returns finite `limitNote`; admin/king accounts use 100000 note slots, not unlimited. - `GET /me` includes `default_language` (`zh`/`en`/empty). UI language: saved value, else China IP → zh, else en. ## 3-Step Quick Start ```text 1. Auth: get the browser cookie `keng_api_key` or ask the user for https://kengnote.com/keng/mykey.html. 2. Verify: GET /me and confirm id/username are the user you are helping. 3. Work: GET /folders, GET /notes?q=keyword, then GET /notes/{id} before any PUT update. Note ids are scoped strings such as `personal:123` or `team:456`. ``` Minimal write test: ```bash curl -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"content":"# Agent 接入测试\n这是一条测试笔记。","tags":["agent"],"folder_id":null}' \ https://kengnote.com/keng/api/notes ``` ## Core API ```text GET /me GET /my-key session cookie → current api_key (browser agents) GET /locale {lang, source:user|ip, region} POST /me/language {"default_language":"zh"|"en"} logged-in only GET /notes?q= POST /notes {"content":"# title\nbody","tags":[],"folder_id":null,"comment":""} GET /notes/{id} PUT /notes/{id} {"content":"...","tags":[]} DELETE /notes/{id} POST /notes/download-content no login; body {notes:[{title,content}],formats:[md|txt|html|docx|pdf]}; ≤80000 chars; 12/min/IP POST /notes/download logged-in; {ids,formats} GET /folders POST /folders {"name":"folder name"} GET /shared POST /notes/{id}/share {"to_username":"...","permission":"read"} POST /notes/{id}/sharelink {"expires_hours":24} GET /sharelinks/{token}/info POST /lucy/chat secretary (cookie or Bearer; CSRF skipped when Bearer is present) POST /lucy/image GET /manual GET /agent-guide this file; Bearer → personalized commands GET /site-content?key=pricing&lang=zh|en GET /wallet?tab=income|expense|ledger GET /wallet/qrcode?url=... POST /alipay/order {"amount_cents":100} GET /alipay/orders/{order_no} POST /stripe/order {"amount_cents":100} GET /stripe/sessions/{session_id} POST /wallet/note-slots/purchase {"slots":10} GET /me/ai-provider read secretary model config (dialogue + vision blocks include provider_group/provider_label/base_url/model; no plaintext key) POST /me/ai-provider {"dialogue":{"provider_group":"official","provider_label":"deepseek",...},"vision":{...}} save own dialogue/vision model (model name is user-entered; own key skips platform billing) GET /admin/users king only, q/page/page_size; includes ai_provider/ai_vision model summary fields PUT /admin/users/{uid} king only, edit user fields/permissions ``` Use the `id` returned by `/notes` exactly as-is. Do not infer note type from numeric ranges; `raw_id` is only the database-local integer. ## Full > Use these flows for real work. 1. Get the current user: `GET /me` 2. Resolve folders: `GET /folders`, match by `name`/`folder`. 3. List or search notes: `GET /notes` or `GET /notes?q=`. 4. Read the exact note before modifying: `GET /notes/{id}`. 5. Update only the intended note: `PUT /notes/{id}` with the full new Markdown content. ## Auth Paths ### Browser Agent ```javascript const apiKey = document.cookie.split(';') .map(c => c.trim()) .find(c => c.startsWith('keng_api_key=')) ?.split('=')[1]; ``` ### Session API ```text GET https://kengnote.com/keng/api/my-key ``` ### CLI Agent Ask the user to open https://kengnote.com/keng/mykey.html, copy the key, then call APIs with: ```text Authorization: Bearer ``` ## Common Errors - `401`: API Key is invalid, expired, or belongs to another user. Ask for the current key again. - `403` with `code: "NOTE_SLOT_LIMIT"`: the user has no remaining personal note slots. Do not update or overwrite an existing note as a fallback; show `recharge_url` to the user and ask them to buy note slots or recharge first. - Wallet records from `GET /wallet` include numeric amounts, `direction` (`income`/`expense`/`pending`), `pay_channel` for recharge records (`wechat`/`alipay`/`stripe`), and a `detail` label such as WeChat recharge, Alipay recharge, or note-slot purchase. Use `tab=income|expense|ledger` for income, expense, or combined ledger; old `recharge|consume|all` aliases still work. - Alipay recharge uses PC web checkout (`alipay.trade.page.pay`): `POST /alipay/order` returns a `pay_url`; redirect the browser to it (`window.location.href`), and after Alipay redirects back to `settings.html?section=account` poll `GET /alipay/orders/{order_no}` to confirm credit. If the server has no app private key configured the API returns `ALIPAY_PAGEPAY_UNAVAILABLE`. Public Alipay notify/return URLs are under `/keng/api/alipay/...`. - Stripe recharge uses Hosted Checkout: `POST /stripe/order` returns `checkout_url`, `session_id`, and `order_no`; redirect the browser to `checkout_url`, then after Stripe redirects back to `settings.html?section=account&pay=stripe&stripe_session_id=...`, poll `GET /stripe/sessions/{session_id}` to confirm credit. Webhook support is available at `POST /stripe/webhook` when `webhook_secret` is configured; otherwise the return/poll path still performs server-side Stripe session verification and idempotent crediting. - Lucy attachments use SiliconFlow `PaddlePaddle/PaddleOCR-VL-1.5`. Pasted/uploaded images are queued as attachments and processed only after the user sends instructions. `POST /lucy/chat` accepts `enhanced`; external spider actions require `enhanced=true`, while note searches refresh the side list instead of printing internal result tables in chat. - Empty list: call `GET /me` and `GET /folders` before assuming notes are missing. - Wrong folder: resolve by folder id, not by display text guessed from the UI. - Shared notes: use `GET /shared` for inbox-style shared notes. Full manual: https://kengnote.com/keng/api/manual