Create project journal entry
Creates a new project journal entry to document important project events, observations, feedback, or notes.
What to include:
- projectId (required): The UUID of the project this entry belongs to
- body (required): The journal entry content in HTML or Markdown format. Supports rich text formatting including paragraphs, headings, highlighting, and lists
- mood (optional): Mood indicator - Sad (problems/escalations), Neutral (factual), or Happy (wins/progress). Defaults to Neutral if not provided
- reminder (optional): ISO 8601 date string for setting a reminder about this entry
Common use cases:
- Documenting customer feedback or complaints
- Recording internal findings and observations
- Capturing important conversations or decisions
- Noting risks or opportunities
- Tracking project mood and sentiment over time
Validation:
- The projectId must exist and be accessible to the authenticated user
- Body content cannot be empty
- Reminder date must be a valid ISO 8601 date string
What is returned: The complete created journal entry with all fields populated, including the body converted to HTML format.
POST
/projects/journalAuthorization
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/jsonbodystringrequiredThe journal entry content in HTML or Markdown format. Supports rich text formatting including paragraphs, headings, lists, and highlighting. 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>
```
**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>
```
**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>
```
**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>
```
**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>
```
### 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 and cannot be empty.
moodstringMood indicator for the journal entry. Use Sad for negative reactions, problems, or escalations. Use Neutral for factual observations or open-ended notes. Use Happy for positive feedback, wins, or progress. If not provided, defaults to Neutral.
Allowed:
SadNeutralHappyprojectIdstringrequiredThe UUID of the project this journal entry belongs to. The project must exist and be accessible to the authenticated user.
reminderstringOptional reminder date in ISO 8601 format (YYYY-MM-DD). Use this to set a follow-up reminder for the journal entry. Useful for escalation checks, review points, or follow-up tasks.
Responses
200
bodystringrequiredThe journal entry content converted to HTML format with all formatting preserved. Includes paragraphs, headings, lists, highlighting, and other rich text elements.
createdAtstringrequiredISO 8601 timestamp indicating when the journal entry was created
createdBystringrequiredUUID of the user who created this journal entry
idstringrequiredUnique identifier for the journal entry (UUID)
lastUpdatedstringrequiredISO 8601 timestamp indicating when the journal entry was last updated. This is automatically updated whenever any field is modified via PATCH.
moodstringrequiredMood indicator for the journal entry. Sad indicates negative reactions, problems, or escalations. Neutral indicates factual observations or open-ended notes. Happy indicates positive feedback, wins, or progress.
Allowed:
SadNeutralHappyprojectIdstringrequiredThe UUID of the project this journal entry belongs to
reminderobject | nullrequiredOptional reminder date in ISO 8601 format (YYYY-MM-DD). Set when creating or updating an entry to schedule a follow-up reminder. Null if no reminder is set.
400Validation errors
errorsobjectmessagestringstatusCodenumber401Unauthorized - Invalid or missing authentication token
403Forbidden - Insufficient API scopes or permissions
Request
curl -X POST "https://leadtime.app/api/public/projects/journal" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"body": "<h1>Project Update</h1><p>Today we completed milestone 1.</p>",
"mood": "Neutral",
"projectId": "550e8400-e29b-41d4-a716-446655440000",
"reminder": "2024-12-31"
}'const response = await fetch("https://leadtime.app/api/public/projects/journal", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({
"body": "<h1>Project Update</h1><p>Today we completed milestone 1.</p>",
"mood": "Neutral",
"projectId": "550e8400-e29b-41d4-a716-446655440000",
"reminder": "2024-12-31"
})
});import requests
response = requests.post(
"https://leadtime.app/api/public/projects/journal",
headers={
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
},
json={
"body": "<h1>Project Update</h1><p>Today we completed milestone 1.</p>",
"mood": "Neutral",
"projectId": "550e8400-e29b-41d4-a716-446655440000",
"reminder": "2024-12-31"
},
)Response
{
"body": "<h1>Project Update</h1><p>Today we completed milestone 1.</p>",
"createdAt": "2024-01-15T10:30:00Z",
"createdBy": "550e8400-e29b-41d4-a716-446655440000",
"id": "550e8400-e29b-41d4-a716-446655440000",
"lastUpdated": "2024-01-16T14:20:00Z",
"mood": "Neutral",
"projectId": "550e8400-e29b-41d4-a716-446655440000",
"reminder": "2024-12-31"
}{
"errors": {
"body": [
"Body content is required"
],
"projectId": [
"Project ID is required"
]
},
"message": "Bad Request",
"statusCode": 400
}Unauthorized - Invalid or missing authentication token
Forbidden - Insufficient API scopes or permissions