Create a project documentation page or folder
Creates a project documentation page or folder. Omit kind for the backward-compatible Page default.
What to include:
- A required title field whose value can be empty
- For a page (the default kind), a required content field whose value can be empty and optional active tag UUIDs
- For a folder, kind
Folderwith content and tags omitted - Optional parent and sibling UUIDs to place either node in the documentation tree
Content format:
- Page content accepts HTML or Markdown input
- Content is automatically converted to internal ProseMirror format for storage
- Supports rich text formatting including headings, lists, tables, and code blocks
- When retrieved via GET endpoint, content is returned as HTML
Retry safety:
- This create operation does not accept an idempotency key
- If the outcome is unknown after a network failure, read the project tree and reconcile the intended parent, kind, and title before retrying to avoid a duplicate node
Permissions:
- Requires “manageDocumentation” permission and access to the project
- The new node is automatically associated with the authenticated user as the author
POST
/projects/documentationAuthorization
AuthorizationOAuth2 access token · headerrequiredScopes:
api:writeor
AuthorizationBearer token (JWT) · headerrequiredQuery parameters
fieldsToReturnstringComma-separated list of top-level response fields to return. Overrides the endpoint compact default unless responseShape=full is used.
responseShapestringAdvanced override. Omit for the endpoint compact default. Use full only when you need the complete endpoint response, including nested fields that are not selectable with fieldsToReturn.
Allowed:
compactfullHeader parameters
LT-Response-ShapestringAdvanced override. Set to full only when you need the complete endpoint response, including nested fields that are not selectable with fieldsToReturn.
Allowed:
fullRequest body
requiredapplication/jsonafterNodeIdstringSibling node ID after which the new page is inserted. It must use the same parent.
contentstringAccepts Markdown or HTML for complex formatting. This content is rendered by the Leadtime rich editor, not by a plain Markdown viewer.
For quick/simple text, Markdown is acceptable. For polished user-facing content from an agent or integration, prefer structured HTML because it preserves editor blocks, links, and layout more predictably.
Use only the nodes and marks documented below for this field. Supported editor features differ by endpoint and field. Choose formatting for readability, not decoration: use headings for real sections, paragraphs for narrative text, lists or tables for structured facts, blockquotes for quoted context, callouts for important outcomes/risks/notes when supported, and explicit anchors for links. Do not rely on bare URLs or Markdown links when the link must be clickable; use explicit anchors such as <a href="https://example.com" target="_blank" rel="noopener noreferrer nofollow">link text</a>.
In HTML you can use:
## Node Types and Marks
### Nodes
**paragraph**
Type: block
Content: inline* (inline only — do not use block tags such as <p> inside; use e.g. <br>, <strong>, <em>, <span>…)
Default paragraph. extraPlaceholder is an internal structure for the editor to show a ghost placeholder in empty “template” lines (ProseMirror JSON fragment or null). For normal agent output leave extraPlaceholder as null. Only set it if you are intentionally mirroring a field placeholder the user already has in the open editor; do not set random placeholder data for free-form answers.
Atts:
- extraPlaceholder: null
```html
<p class="paragraph-base" extraplaceholder="null/some-value"></p>
```
**heading**
Type: block
Content: inline* (inline only — do not use block tags such as <p> inside; use e.g. <br>, <strong>, <em>, <span>…)
Atts:
- level: 1
```html
<h1 class="heading-base"></h1>
```
**bulletList**
Type: block list
Content: listItem+
Atts: none
```html
<ul class="list-base"><li></li></ul>
```
**hardBreak**
Type: inline
Atts: none
```html
<br>
```
**horizontalRule**
Type: block
Atts: none
```html
<hr class="hr-base">
```
**orderedList**
Type: block list
Content: listItem+
Atts:
- start: 1
- type: null
```html
<ol class="order-list-base" type="null/some-value"><li></li></ol>
```
**listItem**
Content: (paragraph|list)* (paragraphs and/or lists, in any order)
Atts: none
```html
<li></li>
```
**blockquote**
Type: block
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Atts: none
```html
<blockquote class="blockquote-base"><p class="paragraph-base"></p></blockquote>
```
**codeBlock**
Type: block
Content: text* (text only (plus marks if applicable), no block wrappers)
Atts:
- language: null
```html
<pre><code class="language-null/some-value"></code></pre>
```
**table**
Type: block
Content: tableRow+
Atts: none
```html
<table style="width: 0px;"><colgroup></colgroup><tbody><tr></tr></tbody></table>
```
**tableRow**
Content: (tableCell | tableHeader)*
Atts: none
```html
<tr></tr>
```
**tableHeader**
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Atts:
- colspan: 1
- rowspan: 1
- colwidth: null
- align: null
```html
<th colspan="1" rowspan="1" colwidth="null/some-value" style="text-align: null/some-value;"><p class="paragraph-base"></p></th>
```
**tableCell**
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Atts:
- colspan: 1
- rowspan: 1
- colwidth: null
- align: null
```html
<td colspan="1" rowspan="1" colwidth="null/some-value" style="text-align: null/some-value;"><p class="paragraph-base"></p></td>
```
**callout**
Type: block
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Callout / info box. The icon attr is an emoji shortcode (e.g. :information_source:, :warning:); it appears on the callout. Body is block content (paragraphs, lists, etc.) — use normal block HTML such as <p class="paragraph-base"> inside the callout <div>. data-type is "callout".
Atts:
- icon: :information_source:
```html
<div data-type="callout" icon=":information_source:"><p class="paragraph-base"></p></div>
```
**condition**
Type: block
Content: conditionBody (a single condition body block)
This node conditionally renders its content based on a set of rules. The rules are defined in the 'conditions' attribute.
'conditions' is an object like: { type: 'and' | 'or', expressions: Array<Expression | ConditionGroup> }.
An 'Expression' is { field: string, operator: string, value: any }.
A 'ConditionGroup' is a nested { type: 'and' | 'or', expressions: [...] }.
Example for an expression: { field: 'invoice.total', operator: 'gt', value: 100 } means 'if invoice total is greater than 100'.
Supported operators typically include: eq (equals), neq (not equals), gt (greater than), gte (greater than or equal to), lt (less than), lte (less than or equal to), contains, in, is_true, is_false, etc. Check editor UI for available fields and operators.
ALL FIELDS CAN ONLY BE EXISTING VARIABLES. DO NOT INVENT NEW FIELDS.
Atts:
- conditions: {
"type": "and",
"expressions": []
}
```html
<condition conditions="{"type":"and","expressions":[]}"><condition-body><p class="paragraph-base"></p></condition-body></condition>
```
**conditionBody**
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Atts: none
```html
<condition-body><p class="paragraph-base"></p></condition-body>
```
**emoji**
Type: inline
Inline emoji. icon is a colon shortcode (e.g. :thumbsup:, :white_check_mark:) stored in data-icon; body is often empty. Use names your emoji set supports; avoid inventing invalid shortcodes in final HTML if you need them to render.
Atts:
- icon: :smile:
```html
<span data-type="emoji" data-icon=":smile:"></span>
```
**entity**
Type: inline
Inline link chip to a Leadtime entity (task, project, etc.), usually from the !-picker or by pasting a leadtime link. Display text is #title; data-type is "entity".
- entityId: Stable id of the target entity (e.g. task or project id). Use ids from the Public API or the user’s context; do not fabricate ids.
- type: What kind of entity is linked (e.g. task, project) — must be consistent with entityId in your workspace.
- title: Shown as the visible #label after the chip; should match the real entity title.
- data: Optional extra JSON the client provides (may be empty). Do not put secrets in HTML.
If the user has not given a real entity, use the API to search or create—do not guess UUIDs or labels.
Atts:
- entityId: null
- type: null
- title: null
- data: {}
```html
<span data-type="entity" entityid="null/some-value" type="null/some-value" title="null/some-value" data="[object Object]">#null/some-value</span>
```
**appFile**
Type: block
Block for a file attachment that already exists in the workspace.
- fileId: Id from Leadtime file storage. Must be real; do not make up.
- filename and size: Should match the stored file. Use the app upload or API to get a file id; do not embed arbitrary ids.
Atts:
- fileId:
- filename:
- size: 0
```html
<div data-type="appFile" fileid="" filename="" size="0"></div>
```
**appImage**
Type: block
Block for an image file already uploaded in Leadtime.
- fileId: Id of the stored image. Must be a real uploaded file; do not invent.
- filename: Display name; should match the file.
- width, align, size: Layout as in the editor. If no file id is available, obtain one via upload/API before outputting this node with a fake id.
Atts:
- fileId:
- filename:
- width: 500
- align: left
- size: 0
```html
<div data-type="appImage" fileid="" filename="" width="500" align="left" size="0"></div>
```
**mention**
Type: inline
Mentions a workspace member (inserted in the app via the @-picker). The visible label is @name.
- id: Leadtime user/employee id for the mentioned person. Must match a real user in the workspace; do not invent ids—resolve people from context or the Public API.
- name: Display name for the @mention label. Should match the user shown for id.
HTML must keep data-type="mention" with data-id and data-name in sync; plain text in the node is the visible @name.
Atts:
- id: null
- name: null
```html
<span data-type="mention" data-name="null/some-value" data-id="null/some-value" id="null/some-value" name="null/some-value">@null/some-value</span>
```
**pageBreak**
Type: block
Page break for PDF/print output (void <page-break> element). Inserts a hard page break when exporting. Use sparingly where the user asked for a new printed page, not for normal on-screen line breaks (use hardBreak/paragraphs instead).
Atts: none
```html
<page-break></page-break>
```
**editorPlaceholder**
Type: block
Content: inline* (inline only — do not use block tags such as <p> inside; use e.g. <br>, <strong>, <em>, <span>…)
Used in task-type / template fields as a single editable “field” slot. Renders as a <placeholder> block with inline* content (label/instructions) inside. Prefer normal paragraph nodes for free-form user content; use this when reproducing a structured template the user is editing, not for generic text.
Atts: none
```html
<placeholder></placeholder>
```
**appVideo**
Type: block
Block for a workspace video file already uploaded in Leadtime (not a generic external embed).
- fileId: Id of the stored file. Must be a file that actually exists in the workspace after upload; do not fabricate.
- filename: Display name; should match the file.
- width, align, size: Layout hints as in the editor; keep realistic values. If you do not have a file id, use the file upload or Public API first—do not guess ids.
Atts:
- fileId:
- filename:
- width: 500
- align: left
- size: 0
```html
<div data-type="appVideo" fileid="" filename="" width="500" align="left" size="0"></div>
```
**collapse**
Type: block
Content: collapseTitle collapseBody (a collapse title node, then a collapse body)
Expandable/collapsible section. Required structure: one collapseTitle (summary, inline) then one collapseBody (blocks) as direct children, matching data-type= collapseTitle / collapseBody tags under <collapse>. Do not use title/body nodes outside of a collapse.
Atts: none
```html
<collapse><collapse-title></collapse-title><collapse-body><p class="paragraph-base"></p></collapse-body></collapse>
```
**collapseBody**
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Expandable body of a collapse. Only use as sibling of collapseTitle inside a collapse; holds the block content that shows when expanded.
Atts: none
```html
<collapse-body><p class="paragraph-base"></p></collapse-body>
```
**collapseTitle**
Content: inline* (inline only — do not use block tags such as <p> inside; use e.g. <br>, <strong>, <em>, <span>…)
Clickable title row of a collapse block. Only use inside a collapse that also has collapseBody; content is the summary line shown when collapsed.
Atts: none
```html
<collapse-title></collapse-title>
```
**variable**
Type: inline
Document/template variable token (span with data-type="variable" and data-id).
- id: Variable key, often scoped (e.g. currentUser.firstName, project.name). Only use keys that exist for the document type you are in; product docs list the allowed variable ids. Do not invent new variable names in HTML for production templates.
Atts:
- id: null
```html
<span data-type="variable" data-id="null/some-value" id="null/some-value"></span>
```
**embedVideo**
Type: block
Embeds a third-party video in an iframe. The div carries data-video-embed with data-embed-url (iframe src) and data-original-url (canonical page URL).
- embedUrl: Must be a real embed/iframe URL (e.g. YouTube embed) that matches originalUrl.
- originalUrl: Human-facing link to the video page; keep it in sync with embedUrl. Do not leave placeholder URLs in final HTML if you claim a real video.
- Public API HTML may instead use <div data-type="embedVideo" src="supported provider URL" width="640" align="center"></div>. The server derives embedUrl. width is an optional positive integer; align is optionally left, center, or right.
Atts:
- originalUrl:
- embedUrl:
- width: null
- align: null
```html
<div originalurl="" embedurl="" width="null/some-value" align="null/some-value" data-video-embed="" data-original-url="" data-embed-url=""><iframe src=""></iframe></div>
```
### Marks
**link**
Atts:
- href: null
- target: _blank
- rel: noopener noreferrer nofollow
- class: null
- title: null
```html
<a target="_blank" rel="noopener noreferrer nofollow" href="">link text example</a>
```
**bold**
Atts: none
```html
<strong>bold text example</strong>
```
**code**
Atts: none
```html
<code>code text example</code>
```
**italic**
Atts: none
```html
<em>italic text example</em>
```
**strike**
Atts: none
```html
<s>strike text example</s>
```
**underline**
Atts: none
```html
<u>underline text example</u>
```
This field is required for pages but must be omitted for folders. Empty page content is allowed.
kindstringNode kind. Omit for the backward-compatible Page default. Folders do not accept content or tags.
default: "Page"
Allowed:
FolderPageparentIdstringFolder node ID for the new page. The folder must belong to the same project and workspace.
projectIdstringrequiredID of the project this documentation page belongs to. Must be a valid UUID of an existing project in the workspace.
tagsstring<uuid>[]Active documentation tag UUIDs for a page. Folders do not accept tags.
titlestringrequiredRequired title field. Its value can be empty. An empty title is shown as "Untitled" in navigation.
Responses
200
contentobject | nullrequiredComplete canonical page content serialized as HTML. This response never returns Markdown or the internal editor document. Accepts Markdown or HTML for complex formatting. This content is rendered by the Leadtime rich editor, not by a plain Markdown viewer.
For quick/simple text, Markdown is acceptable. For polished user-facing content from an agent or integration, prefer structured HTML because it preserves editor blocks, links, and layout more predictably.
Use only the nodes and marks documented below for this field. Supported editor features differ by endpoint and field. Choose formatting for readability, not decoration: use headings for real sections, paragraphs for narrative text, lists or tables for structured facts, blockquotes for quoted context, callouts for important outcomes/risks/notes when supported, and explicit anchors for links. Do not rely on bare URLs or Markdown links when the link must be clickable; use explicit anchors such as <a href="https://example.com" target="_blank" rel="noopener noreferrer nofollow">link text</a>.
In HTML you can use:
## Node Types and Marks
### Nodes
**paragraph**
Type: block
Content: inline* (inline only — do not use block tags such as <p> inside; use e.g. <br>, <strong>, <em>, <span>…)
Default paragraph. extraPlaceholder is an internal structure for the editor to show a ghost placeholder in empty “template” lines (ProseMirror JSON fragment or null). For normal agent output leave extraPlaceholder as null. Only set it if you are intentionally mirroring a field placeholder the user already has in the open editor; do not set random placeholder data for free-form answers.
Atts:
- extraPlaceholder: null
```html
<p class="paragraph-base" extraplaceholder="null/some-value"></p>
```
**heading**
Type: block
Content: inline* (inline only — do not use block tags such as <p> inside; use e.g. <br>, <strong>, <em>, <span>…)
Atts:
- level: 1
```html
<h1 class="heading-base"></h1>
```
**bulletList**
Type: block list
Content: listItem+
Atts: none
```html
<ul class="list-base"><li></li></ul>
```
**hardBreak**
Type: inline
Atts: none
```html
<br>
```
**horizontalRule**
Type: block
Atts: none
```html
<hr class="hr-base">
```
**orderedList**
Type: block list
Content: listItem+
Atts:
- start: 1
- type: null
```html
<ol class="order-list-base" type="null/some-value"><li></li></ol>
```
**listItem**
Content: (paragraph|list)* (paragraphs and/or lists, in any order)
Atts: none
```html
<li></li>
```
**blockquote**
Type: block
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Atts: none
```html
<blockquote class="blockquote-base"><p class="paragraph-base"></p></blockquote>
```
**codeBlock**
Type: block
Content: text* (text only (plus marks if applicable), no block wrappers)
Atts:
- language: null
```html
<pre><code class="language-null/some-value"></code></pre>
```
**table**
Type: block
Content: tableRow+
Atts: none
```html
<table style="width: 0px;"><colgroup></colgroup><tbody><tr></tr></tbody></table>
```
**tableRow**
Content: (tableCell | tableHeader)*
Atts: none
```html
<tr></tr>
```
**tableHeader**
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Atts:
- colspan: 1
- rowspan: 1
- colwidth: null
- align: null
```html
<th colspan="1" rowspan="1" colwidth="null/some-value" style="text-align: null/some-value;"><p class="paragraph-base"></p></th>
```
**tableCell**
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Atts:
- colspan: 1
- rowspan: 1
- colwidth: null
- align: null
```html
<td colspan="1" rowspan="1" colwidth="null/some-value" style="text-align: null/some-value;"><p class="paragraph-base"></p></td>
```
**callout**
Type: block
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Callout / info box. The icon attr is an emoji shortcode (e.g. :information_source:, :warning:); it appears on the callout. Body is block content (paragraphs, lists, etc.) — use normal block HTML such as <p class="paragraph-base"> inside the callout <div>. data-type is "callout".
Atts:
- icon: :information_source:
```html
<div data-type="callout" icon=":information_source:"><p class="paragraph-base"></p></div>
```
**condition**
Type: block
Content: conditionBody (a single condition body block)
This node conditionally renders its content based on a set of rules. The rules are defined in the 'conditions' attribute.
'conditions' is an object like: { type: 'and' | 'or', expressions: Array<Expression | ConditionGroup> }.
An 'Expression' is { field: string, operator: string, value: any }.
A 'ConditionGroup' is a nested { type: 'and' | 'or', expressions: [...] }.
Example for an expression: { field: 'invoice.total', operator: 'gt', value: 100 } means 'if invoice total is greater than 100'.
Supported operators typically include: eq (equals), neq (not equals), gt (greater than), gte (greater than or equal to), lt (less than), lte (less than or equal to), contains, in, is_true, is_false, etc. Check editor UI for available fields and operators.
ALL FIELDS CAN ONLY BE EXISTING VARIABLES. DO NOT INVENT NEW FIELDS.
Atts:
- conditions: {
"type": "and",
"expressions": []
}
```html
<condition conditions="{"type":"and","expressions":[]}"><condition-body><p class="paragraph-base"></p></condition-body></condition>
```
**conditionBody**
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Atts: none
```html
<condition-body><p class="paragraph-base"></p></condition-body>
```
**emoji**
Type: inline
Inline emoji. icon is a colon shortcode (e.g. :thumbsup:, :white_check_mark:) stored in data-icon; body is often empty. Use names your emoji set supports; avoid inventing invalid shortcodes in final HTML if you need them to render.
Atts:
- icon: :smile:
```html
<span data-type="emoji" data-icon=":smile:"></span>
```
**entity**
Type: inline
Inline link chip to a Leadtime entity (task, project, etc.), usually from the !-picker or by pasting a leadtime link. Display text is #title; data-type is "entity".
- entityId: Stable id of the target entity (e.g. task or project id). Use ids from the Public API or the user’s context; do not fabricate ids.
- type: What kind of entity is linked (e.g. task, project) — must be consistent with entityId in your workspace.
- title: Shown as the visible #label after the chip; should match the real entity title.
- data: Optional extra JSON the client provides (may be empty). Do not put secrets in HTML.
If the user has not given a real entity, use the API to search or create—do not guess UUIDs or labels.
Atts:
- entityId: null
- type: null
- title: null
- data: {}
```html
<span data-type="entity" entityid="null/some-value" type="null/some-value" title="null/some-value" data="[object Object]">#null/some-value</span>
```
**appFile**
Type: block
Block for a file attachment that already exists in the workspace.
- fileId: Id from Leadtime file storage. Must be real; do not make up.
- filename and size: Should match the stored file. Use the app upload or API to get a file id; do not embed arbitrary ids.
Atts:
- fileId:
- filename:
- size: 0
```html
<div data-type="appFile" fileid="" filename="" size="0"></div>
```
**appImage**
Type: block
Block for an image file already uploaded in Leadtime.
- fileId: Id of the stored image. Must be a real uploaded file; do not invent.
- filename: Display name; should match the file.
- width, align, size: Layout as in the editor. If no file id is available, obtain one via upload/API before outputting this node with a fake id.
Atts:
- fileId:
- filename:
- width: 500
- align: left
- size: 0
```html
<div data-type="appImage" fileid="" filename="" width="500" align="left" size="0"></div>
```
**mention**
Type: inline
Mentions a workspace member (inserted in the app via the @-picker). The visible label is @name.
- id: Leadtime user/employee id for the mentioned person. Must match a real user in the workspace; do not invent ids—resolve people from context or the Public API.
- name: Display name for the @mention label. Should match the user shown for id.
HTML must keep data-type="mention" with data-id and data-name in sync; plain text in the node is the visible @name.
Atts:
- id: null
- name: null
```html
<span data-type="mention" data-name="null/some-value" data-id="null/some-value" id="null/some-value" name="null/some-value">@null/some-value</span>
```
**pageBreak**
Type: block
Page break for PDF/print output (void <page-break> element). Inserts a hard page break when exporting. Use sparingly where the user asked for a new printed page, not for normal on-screen line breaks (use hardBreak/paragraphs instead).
Atts: none
```html
<page-break></page-break>
```
**editorPlaceholder**
Type: block
Content: inline* (inline only — do not use block tags such as <p> inside; use e.g. <br>, <strong>, <em>, <span>…)
Used in task-type / template fields as a single editable “field” slot. Renders as a <placeholder> block with inline* content (label/instructions) inside. Prefer normal paragraph nodes for free-form user content; use this when reproducing a structured template the user is editing, not for generic text.
Atts: none
```html
<placeholder></placeholder>
```
**appVideo**
Type: block
Block for a workspace video file already uploaded in Leadtime (not a generic external embed).
- fileId: Id of the stored file. Must be a file that actually exists in the workspace after upload; do not fabricate.
- filename: Display name; should match the file.
- width, align, size: Layout hints as in the editor; keep realistic values. If you do not have a file id, use the file upload or Public API first—do not guess ids.
Atts:
- fileId:
- filename:
- width: 500
- align: left
- size: 0
```html
<div data-type="appVideo" fileid="" filename="" width="500" align="left" size="0"></div>
```
**collapse**
Type: block
Content: collapseTitle collapseBody (a collapse title node, then a collapse body)
Expandable/collapsible section. Required structure: one collapseTitle (summary, inline) then one collapseBody (blocks) as direct children, matching data-type= collapseTitle / collapseBody tags under <collapse>. Do not use title/body nodes outside of a collapse.
Atts: none
```html
<collapse><collapse-title></collapse-title><collapse-body><p class="paragraph-base"></p></collapse-body></collapse>
```
**collapseBody**
Content: block+ (one or more block child nodes (e.g. paragraph, list, …))
Expandable body of a collapse. Only use as sibling of collapseTitle inside a collapse; holds the block content that shows when expanded.
Atts: none
```html
<collapse-body><p class="paragraph-base"></p></collapse-body>
```
**collapseTitle**
Content: inline* (inline only — do not use block tags such as <p> inside; use e.g. <br>, <strong>, <em>, <span>…)
Clickable title row of a collapse block. Only use inside a collapse that also has collapseBody; content is the summary line shown when collapsed.
Atts: none
```html
<collapse-title></collapse-title>
```
**variable**
Type: inline
Document/template variable token (span with data-type="variable" and data-id).
- id: Variable key, often scoped (e.g. currentUser.firstName, project.name). Only use keys that exist for the document type you are in; product docs list the allowed variable ids. Do not invent new variable names in HTML for production templates.
Atts:
- id: null
```html
<span data-type="variable" data-id="null/some-value" id="null/some-value"></span>
```
**embedVideo**
Type: block
Embeds a third-party video in an iframe. The div carries data-video-embed with data-embed-url (iframe src) and data-original-url (canonical page URL).
- embedUrl: Must be a real embed/iframe URL (e.g. YouTube embed) that matches originalUrl.
- originalUrl: Human-facing link to the video page; keep it in sync with embedUrl. Do not leave placeholder URLs in final HTML if you claim a real video.
- Public API HTML may instead use <div data-type="embedVideo" src="supported provider URL" width="640" align="center"></div>. The server derives embedUrl. width is an optional positive integer; align is optionally left, center, or right.
Atts:
- originalUrl:
- embedUrl:
- width: null
- align: null
```html
<div originalurl="" embedurl="" width="null/some-value" align="null/some-value" data-video-embed="" data-original-url="" data-embed-url=""><iframe src=""></iframe></div>
```
### Marks
**link**
Atts:
- href: null
- target: _blank
- rel: noopener noreferrer nofollow
- class: null
- title: null
```html
<a target="_blank" rel="noopener noreferrer nofollow" href="">link text example</a>
```
**bold**
Atts: none
```html
<strong>bold text example</strong>
```
**code**
Atts: none
```html
<code>code text example</code>
```
**italic**
Atts: none
```html
<em>italic text example</em>
```
**strike**
Atts: none
```html
<s>strike text example</s>
```
**underline**
Atts: none
```html
<u>underline text example</u>
```
contentEtagobject | nullrequiredQuoted strong ETag for the canonical HTML in this response. Keep the double quotes and send the value unchanged as contentEtag for exact HTML edits.
contentGenerationobject | nullrequiredCurrent server-controlled content generation. Use this value as expectedGeneration for guarded replacement.
min 1
createdAtstringrequiredISO 8601 timestamp indicating when the page was created
guestVisiblebooleanDirect guest-visibility flag for internal callers. Organization members do not receive this field.
idstringrequiredUnique identifier for the documentation page (UUID format)
kindstringrequiredAllowed:
FolderPageparentIdstring<uuid> | nullrequiredprojectIdstringrequiredID of the project this documentation page belongs to (UUID format)
tagsstring<uuid>[]requiredCurrent active documentation tag UUIDs. Folders always return an empty array.
titlestringrequiredTitle of the documentation page. Use a clear, descriptive title so team members can find the page quickly (for example, "Access to production system" or "Prioritizing support cases").
updatedAtstringrequiredISO 8601 timestamp indicating when the page was last updated. This timestamp is automatically updated whenever the page is modified.
userIdstringrequiredUser ID of the person who created this documentation page (UUID format). This is automatically set to the authenticated user when the page is created.
400Validation errors
errorstring | objectHTTP error name or a structured HTTP exception response.
Show propertiesHide properties
One of:
string
stringobject
objectmessagestring | string[] | objectrequiredError message, validation message list, or request-field validation message map.
Show propertiesHide properties
One of:
string
stringstring[]
Array of
stringstringobject
objectstatusCodenumberrequiredHTTP status code for this response.
401Unauthorized - Invalid or missing authentication token
403Forbidden - Insufficient API scopes or permissions
404The project does not exist or is not accessible.
errorstring | objectHTTP error name or a structured HTTP exception response.
Show propertiesHide properties
One of:
string
stringobject
objectmessagestring | string[] | objectrequiredError message, validation message list, or request-field validation message map.
Show propertiesHide properties
One of:
string
stringstring[]
Array of
stringstringobject
objectstatusCodenumberrequiredHTTP status code for this response.
Request
curl -X POST "https://leadtime.app/api/public/projects/documentation" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"afterNodeId": "string",
"content": "<h1>Introduction</h1><p>Content with <strong>formatting</strong>.</p>",
"kind": "Folder",
"parentId": "string",
"projectId": "550e8400-e29b-41d4-a716-446655440000",
"tags": [
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
],
"title": "Getting Started Guide"
}'const response = await fetch("https://leadtime.app/api/public/projects/documentation", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({
"afterNodeId": "string",
"content": "<h1>Introduction</h1><p>Content with <strong>formatting</strong>.</p>",
"kind": "Folder",
"parentId": "string",
"projectId": "550e8400-e29b-41d4-a716-446655440000",
"tags": [
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
],
"title": "Getting Started Guide"
})
});import requests
response = requests.post(
"https://leadtime.app/api/public/projects/documentation",
headers={
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
},
json={
"afterNodeId": "string",
"content": "<h1>Introduction</h1><p>Content with <strong>formatting</strong>.</p>",
"kind": "Folder",
"parentId": "string",
"projectId": "550e8400-e29b-41d4-a716-446655440000",
"tags": [
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
],
"title": "Getting Started Guide"
},
)Response
{
"content": "<h1>Introduction</h1><p>This is a documentation page with <strong>formatting</strong>.</p>",
"contentEtag": "\"pd-3-g0tKc9QdVh3mWQ\"",
"contentGeneration": 3,
"createdAt": "2024-01-15T10:30:00Z",
"guestVisible": true,
"id": "550e8400-e29b-41d4-a716-446655440000",
"kind": "Folder",
"parentId": "70850378-7d3c-4f45-91b7-942d4dfbbd43",
"projectId": "550e8400-e29b-41d4-a716-446655440000",
"tags": [
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
],
"title": "Getting Started Guide",
"updatedAt": "2024-01-15T10:30:00Z",
"userId": "550e8400-e29b-41d4-a716-446655440000"
}{
"error": "string",
"message": "string",
"statusCode": 0
}Unauthorized - Invalid or missing authentication token
Forbidden - Insufficient API scopes or permissions
{
"error": "string",
"message": "string",
"statusCode": 0
}