Productivity & teams
Redmine
Issues, time entries and projects in your Redmine, from your agent.
12 endpoints
Read AppFlowy workspaces, pages and database records through MCP or REST. Connect an agent or prepare workspace reports with automation tools and scripts.
15 tools Read and write
AppFlowy Cloud documents a small REST API for workspaces, the folder tree and database rows, and offers no MCP server for appflowy.com workspaces (checked 25 Oct 2026). Its official MCP service ships with the commercial self-hosted edition. Cotlet runs 15 AppFlowy tools hosted, 7 of them beyond what the public API documents.
| What you need | AppFlowy Cloud API | GitHub MCP server | Cotlet |
|---|---|---|---|
| Read and add database rows | Yes, documented | Yes | Yes |
| Page text, Trash, sharing, publishing | Not documented | Yes, most servers | Yes |
| Sign-in | Token you refresh | Your password in a file | Your own browser session |
| Runs with your computer off | If you host the script | No | Yes, hosted |
| Fixed for you when AppFlowy changes | Yes, official | No | Yes, tested every 12 h |
Checked 25 Oct 2026. Sources: AppFlowy Docs: AppFlowy Cloud OpenAPI reference · AppFlowy: Pricing · AppFlowy self-hosted OpenAPI guide · Zapier: AppFlowy integrations
Use your own account in its Cotlet Cloud Browser.
Connect your agent or create a Cotlet API key.
Ask your agent or send an HTTP request.
We never see your AppFlowy password, and nothing is shared or published until you approve it. Who can see your session
Use MCP with your AI agent, or HTTP requests in n8n, Make, Zapier and scripts. Follow the MCP setup below or jump to the REST guide.
Turn on AppFlowy for agents. Make a Cotlet account, sign in to appflowy.com in the AppFlowy Cloud Browser and press Enable for agents.
Give your agent the address. Put https://cotlet.dev/mcp/v1 in the MCP or connector settings of your client.
Authorize it. Chat apps open a Cotlet sign-in. Code editors, n8n and scripts send an API key made in the console.
AppFlowy shares https://cotlet.dev/mcp/v1 with every other app you enable. Turned AppFlowy on after you connected? Refresh the connector and the AppFlowy tools appear.
Settings > Connectors > Add custom connector
URL: https://cotlet.dev/mcp/v1/connect
Claude Code:
claude mcp add --transport http cotlet-appflowy \
https://cotlet.dev/mcp/v1 \
--header "Authorization: Bearer $COTLET_API_KEY" Settings > Apps & Connectors > Create
MCP server URL: https://cotlet.dev/mcp/v1/connect
Authentication: OAuth // ~/.cursor/mcp.json
{
"mcpServers": {
"cotlet-appflowy": {
"url": "https://cotlet.dev/mcp/v1",
"headers": { "Authorization": "Bearer ${env:COTLET_API_KEY}" }
}
}
} # ~/.codex/config.toml
[mcp_servers.cotlet-appflowy]
url = "https://cotlet.dev/mcp/v1"
bearer_token_env_var = "COTLET_API_KEY" MCP Client Tool (inside an AI Agent)
Transport: HTTP Streamable
URL: https://cotlet.dev/mcp/v1
Auth: Bearer, <your key>
Tool: appflowy_read Make: MCP Client > Call a tool
Zapier: MCP Client by Zapier > Run Tool
Server URL: https://cotlet.dev/mcp/v1
Token: <your key>
Tool: appflowy_write Create a Cotlet API key with access to AppFlowy and its read operations. Store it as COTLET_API_KEY in your environment or automation platform's credential store.
Sign in to AppFlowy in its Cotlet Cloud Browser and enable the app for agents. Your AppFlowy workspace role and page permissions determine accessible records.
curl https://cotlet.dev/api/v1/appflowy/workspaces \
-H "Authorization: Bearer $COTLET_API_KEY" A successful REST call puts the tool output in result. This illustrative response excerpt omits call IDs, messages and credit details.
{
"status": "success",
"app": "appflowy",
"tool": "list_workspaces",
"result": {
"workspaces": [
{
"workspace_id": "b7d1e0a2-3c4f-4a55-9a10-5f2d8e6c1b77",
"name": "Studio Notes",
"role": "owner"
}
]
}
} Read result.workspaces and use a returned workspace_id in page and database reads. Workspace listing has no pagination input.
The page tree defaults to depth two and omits inaccessible pages. It is a navigation view, not an unlimited document export.
Database row lists use fixed pages of 50 records. Pass returned next_cursor unchanged as cursor until null, keeping workspace, database and updated-since filters fixed; there is no limit input.
| Tool | Connect through | Example workflow |
|---|---|---|
| n8n | HTTP Request | Read workspaces, page trees and permitted pages into a document index for your chosen destination. |
| Make | HTTP > Make a request | Combine database fields and paged database rows into a reporting sheet, comparing row IDs and changed cells. |
| Python or Node.js | REST API | Read trash and member records into an owner access review without restoring or sharing content. |
Send Authorization: Bearer <your Cotlet API key> in request headers. You configure the schedule, destination and record comparisons.
Cotlet reads AppFlowy; your workflow steps write to your chosen destination. These HTTP workflows do not require a native Cotlet connector or a prebuilt template.
Python and Node.js can use the same HTTP requests without an AI agent. Keep access keys in credentials, outside shared workflow exports.
The API and MCP reference lists operations and inputs. The REST API guide explains authentication, errors and approvals.
Start here: every other tool takes a workspace_id. Only the owner sees the full member list.
Returns each workspace with its ID, name and your role. Call it first: every other tool needs a workspace_id. It returns the workspaces of the signed-in account only.
MCP callappflowy_read → list_workspaces
REST endpointGET https://cotlet.dev/api/v1/appflowy/workspaces
No parameters.
{
"workspaces": [
{
"workspace_id": "b7d1e0a2-3c4f-4a55-9a10-5f2d8e6c1b77",
"name": "Studio Notes",
"role": "owner"
},
{
"workspace_id": "0e9a6c13-82b4-4d0f-bb21-7a4c93d5e8f1",
"name": "Side Projects",
"role": "member"
}
]
} Returns spaces in the order of the sidebar, then pages and subpages with their ID, name and type (document, grid, board or calendar). Pages you cannot open are left out. Use the page_id from here in get_page, share_page and publish_page.
MCP callappflowy_read → get_page_tree
REST endpointGET https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/page-tree
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
| space string | string | Only this space, by name. |
| depth integer | integer | How many levels of subpages to return. Default 2. |
{
"workspace_id": "workspace_8c41d2"
} {
"spaces": [
{
"name": "General",
"pages": [
{
"page_id": "c41f7a90-5b2e-4c36-8d17-aa03e9b2f5d4",
"name": "Client roadmap",
"type": "document",
"children": []
},
{
"page_id": "6d02be58-91a7-4e0c-b3f4-2c8e7d10a965",
"name": "Tasks",
"type": "grid",
"children": []
}
]
}
]
} Returns name, email and role for each person. Only the owner sees every member. Use it to check who is in the workspace before share_page.
MCP callappflowy_read → list_members
REST endpointGET https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/members
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
{
"workspace_id": "workspace_8c41d2"
} {
"members": [
{
"name": "Maya Brandt",
"email": "maya@example.com",
"role": "owner"
},
{
"name": "Tom Reyes",
"email": "tom@example.com",
"role": "member"
}
]
} Grid, board and calendar databases. Cells are keyed by field name, and select values must match an existing option.
Returns each database with its ID, name and the views it has. Pass the database_id to list_database_fields and list_database_rows.
MCP callappflowy_read → list_databases
REST endpointGET https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/databases
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
{
"workspace_id": "workspace_8c41d2"
} {
"databases": [
{
"database_id": "6d02be58-91a7-4e0c-b3f4-2c8e7d10a965",
"name": "Tasks",
"views": [
"Grid",
"Board"
]
}
]
} Returns each field name and type, and the option names of select fields. Read it before create_database_row or update_database_row so the cells use the field names exactly.
MCP callappflowy_read → list_database_fields
REST endpointGET https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/database-fields
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
| database_id string required | string | Database ID from list_databases. |
{
"workspace_id": "workspace_8c41d2",
"database_id": "database_8c41d2"
} {
"fields": [
{
"name": "Name",
"type": "text"
},
{
"name": "Status",
"type": "select",
"options": [
"To do",
"In progress",
"Done"
]
},
{
"name": "Points",
"type": "number"
}
]
} Returns rows with their ID and cells keyed by field name, 50 to a page, with next_cursor until the list ends. Use updated_since for a daily or weekly run so only changed rows come back.
MCP callappflowy_read → list_database_rows
REST endpointGET https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/database-rows
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
| database_id string required | string | Database ID from list_databases. |
| updated_since string | string | ISO date and time. Only rows changed after it. |
| cursor string | string | Next page cursor from the previous call. |
{
"workspace_id": "workspace_8c41d2",
"database_id": "database_8c41d2"
} {
"rows": [
{
"row_id": "f3a8d6c2-0b17-4e95-a2c4-91d5e7b8036a",
"cells": {
"Name": "Write launch post",
"Status": "In progress",
"Points": 5
}
},
{
"row_id": "29c5e1b7-d4f3-4a80-8e62-b0a7c93d1f58",
"cells": {
"Name": "Fix signup form",
"Status": "To do",
"Points": 3
}
}
],
"next_cursor": null
} Returns the cells and the document content of the row, since every row in AppFlowy is a page of its own. Use it when list_database_rows is not enough, for example to read notes written inside a row.
MCP callappflowy_read → get_database_row
REST endpointGET https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/databases/{database_id}/row
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
| database_id string required | string | Database ID from list_databases. |
| row_id string required | string | Row ID from list_database_rows. |
{
"workspace_id": "workspace_8c41d2",
"database_id": "database_8c41d2",
"row_id": "row_8c41d2"
} {
"row_id": "f3a8d6c2-0b17-4e95-a2c4-91d5e7b8036a",
"cells": {
"Name": "Write launch post",
"Status": "In progress",
"Points": 5
},
"content": "Draft is in the shared folder. Needs a final read."
} Creates the row at the end of the database and returns its ID and cells. A select value must match one option from list_database_fields. The row reaches nobody by itself and is undone with one call, so it does not wait for your OK; people who watch the database see it.
MCP callappflowy_write → create_database_row
REST endpointPOST https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/databases/{database_id}/row
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
| database_id string required | string | Database ID from list_databases. |
| cells object required | object | Cell values keyed by field name from list_database_fields. |
| content string | string | Optional text for the page inside the row. |
{
"workspace_id": "b7d1e0a2-3c4f-4a55-9a10-5f2d8e6c1b77",
"database_id": "6d02be58-91a7-4e0c-b3f4-2c8e7d10a965",
"cells": {
"Name": "Prepare client demo",
"Status": "To do",
"Points": 3
}
} {
"row_id": "b52e8f09-7a3c-4d61-9c84-e0d2a6f1738b",
"cells": {
"Name": "Prepare client demo",
"Status": "To do",
"Points": 3
},
"created_at": "2026-10-25T08:30:00Z"
} Changes only the cells you send and returns the row as it is now. A select value must match one option from list_database_fields. The previous value is in the response, so one more call puts it back; it does not wait for your OK.
MCP callappflowy_write → update_database_row
REST endpointPATCH https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/databases/{database_id}/row
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
| database_id string required | string | Database ID from list_databases. |
| row_id string required | string | Row ID from list_database_rows. |
| cells object required | object | New cell values keyed by field name. Fields you leave out stay as they are. |
{
"workspace_id": "workspace_8c41d2",
"database_id": "database_8c41d2",
"row_id": "row_8c41d2",
"cells": "cells"
} {
"row_id": "f3a8d6c2-0b17-4e95-a2c4-91d5e7b8036a",
"cells": {
"Name": "Write launch post",
"Status": "Done",
"Points": 5
},
"previous": {
"Status": "In progress"
}
} Page text comes back as Markdown, images as links. New pages take Markdown; editing a block inside an existing page is not built.
Returns the page title, its text as Markdown, the last edit time and whether the page is published. Images and files are returned as links only. A database page returns its name and type, and you read its rows with list_database_rows.
MCP callappflowy_read → get_page
REST endpointGET https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/pages/{page_id}
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
| page_id string required | string | Page ID from get_page_tree. |
{
"workspace_id": "workspace_8c41d2",
"page_id": "page_8c41d2"
} {
"page_id": "c41f7a90-5b2e-4c36-8d17-aa03e9b2f5d4",
"name": "Client roadmap",
"type": "document",
"content": "# Client roadmap\n\n- Kickoff call\n- Design review\n- Launch",
"published": false,
"updated_at": "2026-10-22T14:05:00Z"
} Creates the page and returns its ID. It appears in the sidebar for everyone with access to that space, and it is moved to Trash with one call if you do not want it, so it does not wait for your OK.
MCP callappflowy_write → create_page
REST endpointPOST https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/pages
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
| name string required | string | Page title. |
| space string | string | Space name from get_page_tree. |
| parent_page_id string | string | Create it as a subpage of this page. |
| content string | string | Page text as Markdown. |
{
"workspace_id": "workspace_8c41d2",
"name": "Jane Doe"
} {
"page_id": "d8a41c75-e6b2-4f03-8719-5c0e3b9a2d64",
"name": "Meeting notes 25 Oct",
"space": "General",
"type": "document"
} Returns each deleted item with its ID, name, type and deletion time, newest first. Deleted database row pages are listed too. Use the trash_id with restore_from_trash.
MCP callappflowy_read → list_trash
REST endpointGET https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/trash
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
{
"workspace_id": "workspace_8c41d2"
} {
"items": [
{
"trash_id": "a90c3e74-2d58-4b1f-9e06-c7f1d8a52b39",
"name": "Q4 plan",
"type": "document",
"deleted_at": "2026-10-23T09:12:00Z"
},
{
"trash_id": "7e4b1d62-c035-4f98-a1d7-3b9e0c85f246",
"name": "Onboarding checklist",
"type": "document",
"deleted_at": "2026-10-21T16:40:00Z"
}
]
} Puts the item back in the sidebar or the database it came from and returns where it went. Undone by moving it to Trash again, so it does not wait for your OK.
MCP callappflowy_write → restore_from_trash
REST endpointPOST https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/trash/{trash_id}/restore
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
| trash_id string required | string | Item ID from list_trash. |
{
"workspace_id": "workspace_8c41d2",
"trash_id": "trash_8c41d2"
} {
"restored": true,
"name": "Q4 plan",
"page_id": "a90c3e74-2d58-4b1f-9e06-c7f1d8a52b39",
"space": "General"
} Both reach people outside your sidebar, so both wait for your OK. Guests outside the workspace need Pro.
Makes the page readable by anyone with the link and returns the link. Check the page with get_page first, because its text becomes public. By default you confirm each call; you can switch that off for this tool.
MCP callappflowy_write → publish_page
REST endpointPOST https://cotlet.dev/api/v1/appflowy/workspaces/{workspace_id}/pages/{page_id}/publish
| Name | Type | Description |
|---|---|---|
| workspace_id string required | string | Workspace ID from list_workspaces. |
| page_id string required | string | Page ID from get_page_tree. |
{
"workspace_id": "workspace_8c41d2",
"page_id": "page_8c41d2"
} {
"page_id": "c41f7a90-5b2e-4c36-8d17-aa03e9b2f5d4",
"published": true,
"url": "https://appflowy.com/studio-notes/client-roadmap"
} The signed-in AppFlowy browser profile, AES-256-GCM, in Finland. No password.
The 15 AppFlowy tools. Never a token or cookie.
The pages and databases your role and page permissions open.
Delete pages or rows, remove members, change billing or settings.
An email with a sign-in link reaches you. We never sign in for you.
Disable for agents, reset the browser or delete the API key.
cotlet.dev rates A+ on Qualys SSL Labs, securityheaders.com and Mozilla Observatory (live results). We have no SOC 2 report or third-party pentest yet.
"You are responsible for maintaining the confidentiality and security of your Account credentials and may not disclose your credentials to any Third Party."
The terms name no bots, scrapers or automated access. They do ask you not to use "unsupported software" and to use the service "as described in the documentation". AppFlowy may suspend access when use "disrupts or poses a security risk" to its systems, with written notice. GitHub servers that keep your password in a file sit closest to the credentials rule; Cotlet never receives the password. We found no public case of an AppFlowy account closed for automation (checked 25 Oct 2026).
Spread a big import, like hundreds of rows, over several runs. Short bursts of writes are what could look like a load problem.
AppFlowy releases often (its site announced desktop 0.14.10 on 25 Oct 2026), and the web app changes with each release. A renamed field or moved menu is fixed on our side. status.cotlet.dev checks the site, console and API every 3 minutes.
| Action | Undo |
|---|---|
| Create a row or page | Move it to Trash in AppFlowy |
| Update row cells | Yes, the old values come back in the answer |
| Restore from Trash | Move it to Trash again |
| Share a page | Change their access in Share; the invite email is out |
| Publish a page | Unpublish it; copies others made stay |
2 of 15 tools ask first: share_page and publish_page, the two that reach people outside the workspace. Rows, pages and restores stay inside it and run at once. Turn the wait off per tool for a scheduled run.
Your page permissions still apply: a Can View page cannot be edited by the agent either.
{
"name": "create_database_row",
"arguments": {
"workspace_id": "b7d1e0a2-3c4f-4a55-9a10-5f2d8e6c1b77",
"database_id": "6d02be58-91a7-4e0c-b3f4-2c8e7d10a965",
"cells": {
"Name": "Prepare client demo",
"Status": "To do",
"Points": 3
}
}
} curl -X POST https://cotlet.dev/api/v1/appflowy/workspaces/b7d1e0a2-3c4f-4a55-9a10-5f2d8e6c1b77/databases/6d02be58-91a7-4e0c-b3f4-2c8e7d10a965/row \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"cells":{"Name":"Prepare client demo","Status":"To do","Points":3}}' {
"row_id": "b52e8f09-7a3c-4d61-9c84-e0d2a6f1738b",
"cells": {
"Name": "Prepare client demo",
"Status": "To do",
"Points": 3
},
"created_at": "2026-10-25T08:30:00Z"
} The same tools answer over REST at /api/v1/appflowy for cron jobs and scripts, on the same key and price, with no AppFlowy token to refresh. A select value that matches no option fails, and a failed call is free. The tools table lists the REST path of each tool.
About $19 a monthfor a team of 5 with one busy Tasks database, 3,300 credits. AppFlowy bills its own plan as before.
| Job | Calls | Credits |
|---|---|---|
| Log new requests as rows, each working day | 5 × 22 | 1,100 |
| Weekly status from the Tasks database | 4 × 4 | 160 |
| Set Status on rows after the standup | 9 × 4 | 360 |
| Weekly meeting notes page | 2 × 4 | 80 |
| Share and publish a client page | 4 × 2 | 80 |
| Restore a page from Trash | 2 × 1 | 20 |
| Cloud Browser, 30 days | 1,500 | |
| Total | 3,300 |
The month is our own example: about 3 new requests each working day, a weekly report and update, 2 client pages. AppFlowy Pro for 5 members is $60 a month on yearly billing. Dollars at the $29 pack rate.
| Credits | Price, one time | Calls at 10 credits | Per 1,000 credits |
|---|---|---|---|
| 5,000 | $29 | 500 | $5.80 |
| 15,000 | $79 | 1,500 | $5.27 |
| 32,000 | $149 | 3,200 | $4.66 |
| 60,000 | $249 | 6,000 | $4.15 |
Only successful calls use credits; failed calls and timeouts cost nothing. At a balance of 0 calls pause, never a surprise charge. Authenticate with the Authorization: Bearer header.
| Option | What it does | Where it stops |
|---|---|---|
| weironz/appflowy_mcp | The widest one: 128 tools in a Rust binary, block editing, Markdown import and export, comments. Apache-2.0, last commit 22 Oct 2026. | Runs on your computer with your AppFlowy email and password in its env. 9 stars, one maintainer. |
| LucasXu0/appflowy_mcp | Small Python server on the REST API, by a developer whose profile lists AppFlowy (11 stars). | Personal repo, not linked by AppFlowy; last commit 31 Mar 2025. |
| Other GitHub servers | About a dozen more (CAREEMER, Rahulk644, hectormr206 and others), most for databases and pages. | You host them and renew the token or password when it fails. |
| AppFlowy self-hosted, commercial | The official MCP service and the full Swagger API. | Only on a server you run with a paid license, not for appflowy.com workspaces. |
If you want every block of every page and do not mind a password in a local file, weironz/appflowy_mcp does more than we do. If only rows matter, Zapier or the documented API is enough. Cotlet fits when an agent should change rows and pages on a schedule from a hosted address, on your own sign-in, with sharing held for your OK.
Behind Cotlet is Take Group sp. z o.o., a software company registered in Poland, EU (VAT PL6342984273), in business since 2019 and founded by Bart Krawczyk (Co-founder, CTO) and Jake Slugocki (Co-founder, SEO, sales and marketing). Questions about the AppFlowy tools go to contact@cotlet.dev.
Yes. Call Cotlet's REST API from a script or an HTTP step in n8n, Make or Zapier with your Cotlet key. MCP is the alternative for AI agents; you do not need to connect an agent to use REST.
Sign up free at https://cotlet.dev, find AppFlowy under Integrations in the console and sign in to appflowy.com in its Cloud Browser. The trial starts with your first app and asks for no card.
Cotlet works in your own account on any plan. The plan still limits what you can do: the Personal plan has one workspace owner, so share_page to a guest needs the Pro plan, where guest editors are unlimited and free (checked 25 Oct 2026). Page permissions apply too: a Can View page cannot be edited.
It reads the text of a page and writes text when it creates a page or a row. Editing a block in the middle of an existing page is not built, and the official REST API does not offer it either.
Not today. The tools work on appflowy.com workspaces. On a commercial self-hosted server, AppFlowy's own MCP service and Swagger API are the better route.
Not in the documented API. The 2 Zapier triggers poll the database for new or changed rows. For an agent, run it on a schedule with list_database_rows and updated_since, so only changed rows come back.
It works in AppFlowy Cloud, which the desktop and mobile apps sync with. Rows and pages the agent writes show up in your apps after the next sync. Pages kept only on your device, without Cloud, are out of reach.
Only the way in differs. Both carry the same 15 tools, inputs and answers, with one API key and one price. Agents use MCP; scripts and HTTP steps use REST.
No. Cotlet is independent and not affiliated with AppFlowy Pte. Ltd.
Free 7-day trial with 2,000 credits, no card needed.
May we use Google Analytics to see which pages help people? It sets cookies only if you accept. No ads, and we never sell data. Cookie policy