Wiki
Read and write the team's internal wiki pages, spaces, databases, the trash, templates, links and tags, comments, and their links to tickets and the help center.
The wiki holds your team’s internal pages: runbooks, policies, notes, plans, databases. It is for members only and never shown to customers. Pages nest under each other and live in the workspace, a teamspace or one member’s private pages.
Scopes: wiki:read to read, wiki:write to change. Guides: Wiki, Databases, Canvas, Links, tags and the graph, Comments and following, Tickets, the help center and Ollie, Import and export.
| Method | Path | Description |
|---|---|---|
GET |
/v1/wiki/pages |
Every page you can see, without its body, to build the tree |
POST |
/v1/wiki/pages |
Create a page: parent_id, space, team_id, title, icon, body_html, position, template, kind, database, props, canvas (all optional) |
GET, PATCH, DELETE |
/v1/wiki/pages/{id} |
Read a page with its body, change it, or delete it for good with its subpages |
POST |
/v1/wiki/pages/{id}/move |
Put it under another page, or at the top level of a space, at a position |
POST |
/v1/wiki/pages/{id}/duplicate |
Copy it with its subpages: parent_id, space, team_id, template, title, position |
POST |
/v1/wiki/pages/{id}/trash |
Move it and its subpages to the trash |
POST |
/v1/wiki/pages/{id}/restore |
Put it back from the trash, with what went with it |
GET |
/v1/wiki/trash |
The pages in the trash, last first |
GET |
/v1/wiki/templates |
The templates you can see |
GET |
/v1/wiki/pages/{id}/revisions |
Its history, newest first |
GET |
/v1/wiki/pages/{id}/revisions/{revisionId} |
One revision with its body |
POST |
/v1/wiki/pages/{id}/revisions/{revisionId}/restore |
Put a revision back as a new version |
GET |
/v1/wiki/search?q= |
Pages matching the words, best first, with a passage around the match |
POST |
/v1/wiki/unfurl |
A link’s title, description and picture, for a bookmark block |
Viewers read. Agents and up create, edit, move, copy and restore pages. GET /v1/search also returns the top wiki pages, in wiki_pages.
Objects
Section titled “Objects”type WikiNode = { id: string; parent_id: string | null; title: string; // "" until named; up to 200 characters (longer is 422) icon: string; // one emoji, or "" position: number; // among its siblings, from 0 version: number; // goes up on every change of title, icon or body updated_at: string; created_by_id: string | null; tags: string[]; // the #tags in its text, lower case kind: "page" | "database" | "canvas"; private: boolean; // yours alone team_id: string | null; // the teamspace it is in journal?: true; // your journal, which holds your daily notes daily_date?: string; // a daily note's day, YYYY-MM-DD template?: true; verified?: true; // verified, and not past the day it was verified until};
type WikiPage = WikiNode & PageSettings & { body_html: string; database: Database | null; // a database's properties and views canvas: Canvas | null; // a canvas's cards and connections props: Record<string, unknown>; // a database row's values, by property id verification: { by: UserRef | null; at: string; until: string | null; expired: boolean } | null; deleted_at: string | null; // in the trash since deleted_by: UserRef | null; created_by: UserRef | null; updated_by: UserRef | null; created_at: string; breadcrumbs: { id: string; title: string; icon: string }[]; // top-level page first children: { id: string; title: string; icon: string }[];};
type PageSettings = { cover: string; // "", "gradient:<name>", or an image: https or /v1/attachments/<id> cover_y: number; // 0..100, which part of an image cover shows full_width: boolean; small_text: boolean; font: "default" | "serif" | "mono"; locked: boolean; // the app opens it read-only until someone unlocks it};created_by_id and created_by are null for a page an API key created, or once its creator deleted their account.
Spaces
Section titled “Spaces”A top-level page lives in a space, and every page under it lives there too:
workspace(the default): every member sees it.private: one member’s own. Nobody else sees it, admins included, nor an API key. AI clients connected as that member read it as them.team: a teamspace, withteam_id. A private team’s pages are its members’ alone; a public team’s every member sees.
Create, move and duplicate take space and team_id for a top-level page; a subpage always lives where its parent does. Moving a page to another space takes its subpages along. A page you can’t see is 404 on every route and never shows in the tree, search, links, the graph, favorites or recent pages.
Edit without overwriting a teammate
Section titled “Edit without overwriting a teammate”Send the version you started from. If someone saved the page since, the API answers 409 with code page_changed and changes nothing:
curl -X PATCH https://api.opendesk.sh/v1/wiki/pages/0192f0c4-... \ -H "Authorization: Bearer od_live_..." \ -H "Content-Type: application/json" \ -d '{"body_html": "<p>Refunds over 100 euros go to the team lead.</p>", "version": 4}'Leave version out to always apply the change. A PATCH that changes nothing keeps the version.
PATCH also takes, without a version:
- The page’s look:
cover,cover_y,full_width,small_text,font,locked. A cover is"",gradient:and one ofdawn,ocean,forest,dusk,sand,slate,rose,lagoon,aurora,ember, or an image: https or one of your attachments. verified: true(withverified_days, 1 to 3650, or without for until someone changes it) verifies the page as you;verified: falsetakes it away. People only: an API key is403.database(a database only, replaced whole) andprops(a row only, merged;nullremoves a value). See Databases.canvas(a canvas only, replaced whole). See Canvas.
None of these moves the version or adds a revision. locked is for the app: the API doesn’t refuse edits to a locked page.
body_html is sanitized before it is stored: only the formatting and blocks below survive, nothing runs, and a value that doesn’t match is dropped. Up to 512 KB.
| Block | HTML |
|---|---|
| Text, headings 1 to 3 | p, h1 to h3, optionally style="text-align: center" (left, center, right, justify) |
| Block colour | data-color (text) and data-bg (background) on p, h1 to h3, li, lists, blockquote, details: gray, brown, orange, yellow, green, blue, purple, pink, red |
| Inline colour | <span data-color>, <mark data-bg>, same tones |
| To-do list | <ul data-type="taskList"><li data-type="taskItem" data-checked="true"> |
| Toggle | <details><summary>…</summary><div data-type="detailsContent">…</div></details> |
| Callout | <div data-type="callout" data-icon="💡" data-tone="yellow">…</div> |
| Columns | <div data-type="columns"> with 2 to 5 <div data-type="column"> |
| Code | <pre><code class="language-go"> |
| Equation | <div data-type="block-math" data-latex>, <span data-type="inline-math" data-latex> |
| Image | <img src alt data-width="1..100" data-align="left|right" data-caption> |
| File, video, audio | <div data-type="file|video|audio" data-src data-name data-size data-mime> |
| Bookmark | <div data-type="bookmark" data-url data-title data-description data-image> |
| Embed | <div data-type="embed" data-url>: the app plays links from the services it knows |
| Table of contents | <div data-type="toc"> |
| Subpage | <div data-type="subpage" data-id="<page id>"> |
| Link to a page | <a data-type="page" data-id="<page id>" href="/wiki/<page id>"> |
| Person | <span data-type="mention" data-id="<user id>"> |
| Ticket, contact | <a data-type="ticket" data-id="<ticket id>" href="/tickets/<number>">, <a data-type="contact" data-id="<contact id>" href="/contacts/<contact id>"> |
| Ticket list | <div data-type="tickets" data-id="<saved view id>" data-limit="10"> |
| Date | <time data-type="date" datetime="2026-11-07">, or with a time; data-reminder="<uuid>" makes it a reminder |
| Inline comment | <span data-comment="<thread id>"> around the text a thread is on |
| Database | <div data-type="database" data-id="<database id>" data-view="<view id>"> |
| Table, divider | table with colgroup, th, td; hr |
Blocks may carry data-block-id (a uuid), so /wiki/<id>#<block id> points at one. Images and files are uploaded as attachments and named by their /v1/attachments/<id> path; saving a page makes the uploads it names its own, readable by whoever can see the page. A page read returns them as short-lived signed links.
POST /v1/wiki/unfurl { url } reads an https page once and answers { title, description, image, site } for a bookmark (agents, wiki:write, 120 a minute per workspace). It refuses private, loopback and link-local addresses; a page it can’t read is 422 unreachable.
Move a page
Section titled “Move a page”curl -X POST https://api.opendesk.sh/v1/wiki/pages/0192f0c4-.../move \ -H "Authorization: Bearer od_live_..." \ -H "Content-Type: application/json" \ -d '{"parent_id": "0192f0c4-...", "position": 0}'parent_id: null moves it to the top level of its space, or of space (and team_id) when you send one. A page can’t move under itself or one of its subpages (422 page_cycle).
Trash and delete
Section titled “Trash and delete”POST /v1/wiki/pages/{id}/trash moves a page and its subpages to the trash. They leave the tree, search, links, the graph and favorites; they can still be read, with deleted_at and deleted_by, and changing, moving or adding under them is 422 page_in_trash.
GET /v1/wiki/trash lists the pages trashed, last first, each a WikiNode with deleted_at, deleted_by, purge_at, subpages (how many went with it) and path (where it was). Pages that went with a parent are not listed on their own.
POST /v1/wiki/pages/{id}/restore puts the page back with what went with it: under its parent when that is in the tree, otherwise at the top of its space. A page not in the trash is 422 not_in_trash; one that went with its parent is 422 trashed_with_parent (restore the page above it).
After 30 days in the trash, pages are deleted for good. DELETE /v1/wiki/pages/{id} deletes one for good at once, from the tree or the trash, with its subpages and their history.
Moving to the trash and deleting follow one rule: admins any page; agents a page they created, when they also created every page under it (otherwise 403, and an admin can). API keys with wiki:write any page they can see.
Templates and copies
Section titled “Templates and copies”A template is a page (with its subpages) that new pages copy. Templates stay out of the tree, search, links and the graph. Create one with POST /v1/wiki/pages and template: true at the top level, or copy a page into one.
POST /v1/wiki/pages/{id}/duplicate copies a page with its subpages, text, icons and look → 201 WikiPage. Links between the copied pages point at the copies, and reminders in the copy belong to whoever made it. Send template: true to save a page as a template, or template: false (with parent_id or space) to make a page from one.
Favorites, recent pages and readers
Section titled “Favorites, recent pages and readers”For people only; an API key is 403.
| Method | Path | Description |
|---|---|---|
GET, PUT |
/v1/wiki/favorites |
Your favorites, in order. PUT { page_ids } (up to 100) replaces them |
GET |
/v1/wiki/recent?limit= |
The pages you opened lately, last first (default 15, at most 50) |
GET |
/v1/wiki/pages/{id}/views |
{ views, people, readers: [{ user, visits, last_at }] }, the latest 20 readers |
GET |
/v1/wiki/daily?from=&to= |
The days you have a daily note, [{ date, id }] (default from 60 days ago to 60 days ahead) |
POST |
/v1/wiki/daily |
Open your note of a day: { date, title, journal_title?, body_html? } |
POST /v1/wiki/daily makes the note when there is none, and the first time also your journal: a private top-level page that holds your daily notes, one per day. The journal stays at the top of your private pages (422 journal_fixed on a move).
Databases
Section titled “Databases”A page with kind: "database" keeps database, its properties and views; its subpages are its rows, each a page with props, its values by property id.
| Method | Path | Description |
|---|---|---|
POST |
/v1/wiki/pages |
{ kind: "database", database? } makes a database; { parent_id: <database>, title, props } adds a row; { parent_id: <database>, template: true } a row template |
GET |
/v1/wiki/databases/{id}/rows |
{ data: DbRow[], templates: WikiNode[] }: every row, in order, and the database’s row templates |
PATCH |
/v1/wiki/pages/{id} |
database on a database, props on a row |
type Database = { properties: DbProperty[]; views: DbView[]; next_id: number };
type DbProperty = { id: string; // [a-z0-9_]{1,24}; the first is the title, "title" name: string; type: "title" | "text" | "number" | "select" | "multi_select" | "status" | "date" | "person" | "checkbox" | "url" | "email" | "phone" | "files" | "relation" | "rollup" | "formula" | "created_time" | "created_by" | "edited_time" | "edited_by" | "unique_id" | "ticket"; options?: { id: string; name: string; color: string }[]; // select, multi_select, status groups?: { id: "todo" | "doing" | "done"; option_ids: string[] }[]; // status number_format?: string; // number, comma, percent, usd, eur, gbp, jpy, chf, cad, aud, inr, brl, huf, pln date_time?: boolean; // dates have a time of day database_id?: string; // relation: the related database rollup?: { relation: string; property: string; fn: string }; formula?: string; prefix?: string; // unique_id: letters before the number description?: string;};
type DbView = { id: string; name: string; type: "table" | "board" | "list" | "gallery" | "calendar" | "timeline" | "chart"; settings?: object };
type DbRow = WikiNode & { props: Record<string, unknown>; cover: string; cover_y: number; excerpt: string; // how its text starts created_at: string; created_by: UserRef | null; updated_by: UserRef | null;};| Type | Stored value |
|---|---|
text, url, email, phone |
a string |
number |
a number |
checkbox |
a boolean |
select, status |
an option id |
multi_select |
option ids |
date |
{ start, end? }: YYYY-MM-DD or RFC 3339 |
person |
user ids of members |
relation |
page ids of rows of the related database |
ticket |
ticket ids |
files |
[{ url, name }] |
unique_id |
numbered by the API for each new row |
title, rollup, formula, created and edited time and by |
worked out by the app, never stored |
database is replaced whole; props is merged, and null removes a value. Neither moves the page’s version. A view’s settings (filters, sorts, grouping, shown properties, calculations) belong to the app, which also works out filters, formulas and rollups. A wrong shape is 422 invalid_database. A database holds up to 100 properties, 50 views, 128 KB of schema and 64 KB of values per row.
Canvas
Section titled “Canvas”A page with kind: "canvas" keeps canvas: cards on an endless board and the connections between them, in the shape of JSON Canvas 1.0 with the wiki’s own card types. Its body_html is a description (empty from the app); its subpages are pages as anywhere else.
| Method | Path | Description |
|---|---|---|
POST |
/v1/wiki/pages |
{ kind: "canvas", canvas? } makes a canvas; left out, an empty one |
PATCH |
/v1/wiki/pages/{id} |
canvas on a canvas, replaced whole |
type Canvas = { nodes: CanvasNode[]; edges: CanvasEdge[] }; // nodes in z order, later above
type CanvasNode = { id: string; // [A-Za-z0-9_-]{1,64}, unique among the nodes x: number; y: number; // within ±1,000,000 width: number; height: number; // 20..20,000 color?: string; // "1".."6" (red, orange, yellow, green, cyan, purple) or "#rrggbb"} & ( | { type: "text"; html: string } // sanitized like a body | { type: "page"; page_id: string } // a page of the workspace | { type: "link"; url: string; title?: string; description?: string; image?: string } // https | { type: "file"; src: string; name: string } // /v1/attachments/<id> or https; name up to 255 | { type: "group"; label?: string } // label up to 200);
type CanvasEdge = { id: string; // as a node's, unique among the edges fromNode: string; toNode: string; fromSide?: "top" | "right" | "bottom" | "left"; // left out: the sides that face each other toSide?: "top" | "right" | "bottom" | "left"; fromEnd?: "none" | "arrow"; // default none toEnd?: "none" | "arrow"; // default arrow color?: string; label?: string; // up to 200};A save keeps the page’s version and adds no revision, and the last save wins. It moves the page’s last edit. Fields that don’t belong to a node’s type are dropped, and default ends are left out. A page card added by a save names a page you can see, not in the trash; a file card added by a save names an attachment of the workspace. Cards already on the canvas stay as they are. Reading a canvas never shows a page’s title: look the page up in your own tree. A wrong shape is 422 invalid_canvas. A canvas holds up to 2,000 nodes, 4,000 edges and 1 MB.
The cards count as the page’s text: page cards and page links in text cards are its links (backlinks, the graph), #tags and ticket mentions in text cards are its tags and ticket links, and the words on cards and connection labels are searched. Duplicates, templates and the trash carry the canvas with the page.
Links, tags and the graph
Section titled “Links, tags and the graph”As a page is saved, the API keeps what it links to and its #tags.
| Method | Path | Description |
|---|---|---|
GET |
/v1/wiki/pages/{id}/backlinks |
The pages linking to it, last edited first (at most 200) |
GET |
/v1/wiki/pages/{id}/mentions |
Unlinked mentions: pages whose text has its title as a phrase, without a link to it (at most 100) |
GET |
/v1/wiki/graph |
Every link between pages you can see, [{ from, to }] |
Backlinks and mentions answer { id, parent_id, title, icon, snippet, updated_at } each. A tag is # with letters, digits, _, - or / and at least one letter, outside code; / nests tags. Tags come back lower case on every page, in tags.
Comments
Section titled “Comments”| Method | Path | Scope | Description |
|---|---|---|---|
GET |
/v1/wiki/pages/{id}/comments |
wiki:read |
{ data: WikiThread[], following }: open and resolved threads, oldest first |
POST |
/v1/wiki/pages/{id}/comments |
wiki:write |
{ body_html, mentions?, thread_id?, quote?, inline? }: a new thread, or a reply with thread_id → 201 WikiThread |
PATCH |
/v1/wiki/comments/{id} |
wiki:write |
{ body_html, mentions? }: its author only |
DELETE |
/v1/wiki/comments/{id} |
wiki:write |
Its author or an admin. Deleting a thread’s first comment deletes the thread |
POST |
/v1/wiki/threads/{id}/resolve |
wiki:write |
{ resolved } |
POST |
/v1/wiki/comments/{id}/reactions |
wiki:write |
{ emoji, on }: one emoji, once per person |
PUT |
/v1/wiki/pages/{id}/follow |
wiki:read |
{ following }: hear about new comments on the page, or stop |
type WikiThread = { id: string; page_id: string; quote: string; // the text an inline thread was started on inline: boolean; // on a run of the text, marked in the body with data-comment created_at: string; resolved_at: string | null; resolved_by: UserRef | null; comments: { id: string; thread_id: string; author: UserRef | null; body_html: string; mentions: string[]; // user ids created_at: string; edited_at: string | null; reactions: { emoji: string; users: string[] }[]; }[];};Writing comments is for agents and up, and for people: an API key reads comments and resolves threads, and is 403 on every other write. A reply reopens a resolved thread. A comment holds up to 20,000 characters and 50 mentions. Following is for people, viewers included.
Reminders
Section titled “Reminders”A date in a page’s body with data-reminder="<uuid>" reminds its owner: whoever first saved the page with that id. On every save the API makes the page’s reminders match its body. The time is the date’s datetime, read in the owner’s notification time zone (a bare date at 09:00); a changed time reminds again, and an id gone from the body is removed. Copies and templates get new ids; a template reminds nobody. Up to 100 reminders per page.
Notifications
Section titled “Notifications”The wiki’s notifications are the wiki group of notification preferences. Their ticket is null:
| Type | When | data |
|---|---|---|
wiki_mention |
Someone newly mentions you in a page’s body, or in a comment | { page_id, page_title, by, preview, thread_id?, comment_id? } |
wiki_comment |
A new comment on a page you follow, or a reply in a thread you wrote in | { page_id, page_title, by, preview, thread_id, comment_id } |
wiki_reminder |
A reminder you set is due | { page_id, page_title, reminder_id, remind_at, label } |
Only people who can see the page hear about it. When a page leaves someone’s sight, or goes to the trash, their notifications about it are removed.
Tickets and the help center
Section titled “Tickets and the help center”| Method | Path | Description |
|---|---|---|
GET |
/v1/tickets/{id}/wiki |
The pages you can see that mention the ticket, last edited first (at most 50). Viewers; tickets:read and wiki:read |
POST |
/v1/kb/articles/from-wiki |
{ page_id, title?, collection_id?, brand_id? } → 201 { article, left_out }: a draft article copied from a page. Agents; kb:write and wiki:read |
A ticket the caller can’t see is 404 on /v1/tickets/{id}/wiki, as on every ticket route. from-wiki turns wiki blocks into article formatting; mentions and links to pages keep only their text, and the workspace’s own files, databases and subpages stay in the wiki, counted in left_out. A page without a title needs title. Nothing stays linked: later edits of the page never reach the article. See Knowledge base.
Ollie writing
Section titled “Ollie writing”POST /v1/wiki/ai/write (agents, wiki:write) has Ollie edit a selection or write from a page, the way the editor’s Ask Ollie does:
{ "mode": "improve", "html": "<p>the selected text</p>", "context_html": "<p>the page around the cursor</p>", "title": "Refund policy", "instructions": "only with mode custom"}mode is improve, fix_grammar, shorter, longer, simplify, more_formal, friendlier, summarize, action_items or explain for a selection (html), continue or summarize from the page (context_html), or custom with instructions. The answer { html } is sanitized like a body and is not saved: insert it with PATCH. Send Accept: text/event-stream to stream it. Typical cost $0.01 for a selection and $0.03 from a page. See AI.
Import and export
Section titled “Import and export”| Method | Path | Description |
|---|---|---|
POST |
/v1/wiki/import |
Make pages from an upload. Agents; wiki:write |
GET |
/v1/wiki/pages/{id}/export?format=&subpages= |
A page as one file, or with subpages=true a zip of it and its subpages. Viewers; wiki:read |
GET |
/v1/wiki/export?format= |
Every page you can see, as Wiki <YYYY-MM-DD>.zip. Viewers; wiki:read |
Import
Section titled “Import”POST /v1/wiki/import takes a multipart form:
| Field | |
|---|---|
files |
One zip (an Obsidian vault, a Notion, Confluence or Google Docs export), or Markdown, text, HTML, CSV and Obsidian .canvas files with the files they use. Repeat the field for each file. Up to 100 MB in all |
parent_id |
Optional: a page to import under (not a database, not in the trash). The import’s top pages go last under it |
space, team_id |
Without parent_id: workspace (default), private (people only) or team with team_id, as for POST /v1/wiki/pages |
curl -X POST https://api.opendesk.sh/v1/wiki/import \ -H "Authorization: Bearer od_live_..." \ -F "space=workspace"→ 201:
{ "pages": 42, "root_ids": ["0192f0c4-..."], "skipped": [{ "path": "Vault/setup.exe", "reason": "executable" }]}pages is how many pages it made, root_ids the pages at the top of the import in order, and skipped what it left out or changed, by its path in the upload:
reason |
|
|---|---|
unsupported |
A kind of file that isn’t imported (Obsidian bases) |
unused |
A file no page uses |
executable |
A program or a script; never imported |
too_large |
A file over 25 MB, or a page source over 4 MB |
unreadable |
A file whose text or table could not be read, or a table that can’t be kept as a database (its rows stay pages) |
body_too_large |
A page whose text is over 512 KB; the page is made without it |
moved_up |
A page deeper than the wiki holds, placed beside its ancestor at the last level |
columns_dropped |
A table’s columns past a database’s 100 properties |
canvas_simplified |
A canvas with cards kept simpler, listed once per canvas: a card for a note’s heading or block (subpath) shows the whole note; an http link, a file or note not in the upload, or a file not taken (a program, too large) is a text card; a group’s background picture and nodes of types JSON Canvas doesn’t define are left out |
canvas_trimmed |
A canvas’s nodes past 2,000 or connections past 4,000, left out |
nested_archive |
An archive inside the upload |
files_limit |
A file past the plan’s limit on imported files; what used it is left out of the page |
All the pages are made in one transaction, with their links, tags, files and a first revision each; imported mentions notify nobody. A wiki_page.created event follows for each page, parents first. An import is refused whole, before anything is stored:
| Status | Code | When |
|---|---|---|
413 |
import_too_large |
The upload is over 100 MB, or over 200 MB unpacked |
422 |
wiki_full |
Its pages don’t fit in the workspace’s 5,000; the message says how many it makes and how many fit |
422 |
page_too_deep |
parent_id is at the 10th level |
422 |
import_into_database |
parent_id is a database |
422 |
import_unsupported |
Not a zip, nor a page source the wiki reads |
422 |
import_unreadable |
The archive could not be read |
422 |
import_too_many_files |
More than 10,000 files or 5,000 pages |
422 |
import_unsafe_path |
The archive holds links, absolute paths or paths that leave it |
422 |
import_compression |
An entry expands over 100 times past 1 MB |
422 |
import_empty |
No pages to import |
429 |
rate_limited |
Over 20 imports an hour in the workspace |
A tree deeper than fits below where it lands is lifted: pages past the last level go beside their ancestor there.
Export
Section titled “Export”format is markdown (the default) or html.
- Markdown is an Obsidian vault: a
.mdper page with YAML front matter (title, icon, dates, tags, a row’s values), its subpages in a folder of the same name beside it,[[links]]between pages, a database as a table of its rows with a.csvbeside it, and a canvas as a.canvasfile (JSON Canvas: text cards in Markdown, page cards as file nodes naming the exported page or a text node when that page isn’t exported, https files as links, groups and connections as they are). - HTML is a standalone page per file, linked by relative paths; a canvas draws its cards where they sit, with its connections.
One page without subpages (or without subpages you can see) is one file, <title>.md (text/markdown; charset=utf-8), a canvas’s <title>.canvas (application/json; charset=utf-8) or <title>.html (text/html; charset=utf-8), its links to pages and files pointing to the app. A zip carries the files its pages use under attachments/, those you may read, up to 1 GB; a link to any other file, or to a page it doesn’t carry, goes to the app. Exports never hold signed links. Every download is Content-Disposition: attachment. Pages in the trash, templates (for the whole wiki) and pages you can’t see are left out; GET /v1/wiki/export with no pages is 422 wiki_empty. An export reads up to 200 MB of page text (422 export_too_large). Zips are limited to 30 an hour per person or key (429 rate_limited) and recorded in the audit log.
Presence
Section titled “Presence”Who is on a page goes through the realtime gateway, on the wiki_page:<wid>:<page_id> topic: join with { "state": "viewing" | "editing" | "idle" }, or { "watch": true } to see others without being shown, and { "team_id": "<tid>" } for a private team’s page. Private pages have no presence. See Realtime.
Limits
Section titled “Limits”- 5,000 pages per workspace, the trash and templates included (
422 wiki_full). - 10 levels deep (
422 page_too_deep). - 512 KB of text and formatting per page (
422 page_too_large). - 100 revisions per page. One person’s edits a few minutes apart share a revision.
- 100 favorites, 100 reminders per page.
- A canvas: 2,000 nodes, 4,000 edges, 1 MB (
422 invalid_canvas). - Imports: 100 MB uploaded, 200 MB unpacked, 10,000 files, 5,000 pages, 25 MB a file, 4 MB a page source; 20 an hour per workspace.
- Exports: 200 MB of page text, 1 GB of files in a zip; 30 zips an hour per person or key.
Events
Section titled “Events”| Event | Data |
|---|---|
wiki_page.created, wiki_page.updated, wiki_page.moved |
{ wiki_page, updated_by }: the page without its body. wiki_page.updated also carries settings, verification, database, props or canvas when those changed; canvas_changed: true instead of canvas when it is over 256 KB (fetch the page) |
wiki_page.deleted |
{ wiki_page_id, wiki_page_ids }: the page and every subpage that went with it; trashed: true when they went to the trash |
wiki_page.restored |
{ wiki_page, wiki_page_ids }: back from the trash |
wiki_comment.changed |
{ page_id, thread_id }: a thread changed; fetch the page’s comments |
Events about a private page go only to its member, and about a private team’s page only to that team. Fetch the page for its text.