Notes API
A note holds text content with optional start/end dates, metadata, and associations to resources, groups, and tags. Each note has a type that controls its display and behavior.
List Notes
Retrieve a paginated list of notes with optional filtering.
GET /v1/notes
Query Parameters
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
Name | string | Filter by name (partial match) |
Description | string | Filter by description (partial match) |
OwnerId | integer | Filter by owner group ID |
Groups | integer[] | Filter by associated group IDs |
Tags | integer[] | Filter by tag IDs |
Ids | integer[] | Filter by specific note IDs |
NoteTypeId | integer | Filter by note type ID |
CreatedBefore | string | Filter by creation date (ISO 8601) |
CreatedAfter | string | Filter by creation date (ISO 8601) |
StartDateBefore | string | Notes starting before this date |
StartDateAfter | string | Notes starting after this date |
EndDateBefore | string | Notes ending before this date |
EndDateAfter | string | Notes ending after this date |
Shared | boolean | Presence flag for shared notes. Include this parameter (for example Shared=1) to return only notes that have a share token. |
MetaQuery | string[] | Filter by metadata conditions (key:value or key:OP:value) |
SortBy | string[] | Sort order (e.g., created_at desc) |
Example
# List all notes
curl http://localhost:8181/v1/notes
# Filter by note type
curl "http://localhost:8181/v1/notes?NoteTypeId=1"
# Filter by owner group
curl "http://localhost:8181/v1/notes?OwnerId=5"
# Filter by date range
curl "http://localhost:8181/v1/notes?StartDateAfter=2024-01-01&StartDateBefore=2024-12-31"
Response
[
{
"ID": 1,
"Name": "Meeting Notes",
"Description": "Notes from the project kickoff meeting...",
"StartDate": "2024-01-15T10:00:00Z",
"EndDate": "2024-01-15T11:30:00Z",
"OwnerId": 5,
"NoteTypeId": 1,
"Meta": {"attendees": ["Alice", "Bob"]},
"CreatedAt": "2024-01-15T12:00:00Z",
"UpdatedAt": "2024-01-15T12:00:00Z",
"Tags": [...],
"Groups": [...],
"Resources": [...],
"NoteType": {...}
}
]
Get Single Note
Retrieve details for a specific note.
GET /v1/note?id={id}
Example
curl http://localhost:8181/v1/note?id=123
Create or Update Note
Create a new note or update an existing one.
POST /v1/note
Parameters
| Parameter | Type | Description |
|---|---|---|
ID | integer | Note ID (include to update, omit to create) |
Name | string | Note title |
Description | string | Note content/body |
OwnerId | integer | Owner group ID |
NoteTypeId | integer | Note type ID |
Groups | integer[] | Associated group IDs |
Tags | integer[] | Tag IDs |
Resources | integer[] | Associated resource IDs |
Meta | string | JSON metadata object |
StartDate | string | Start date (ISO 8601) |
EndDate | string | End date (ISO 8601) |
Example - Create
curl -X POST http://localhost:8181/v1/note \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"Name": "Project Notes",
"Description": "This is the note content...",
"OwnerId": 5,
"NoteTypeId": 1,
"Tags": [1, 2],
"StartDate": "2024-01-15T10:00:00Z"
}'
Example - Update
curl -X POST http://localhost:8181/v1/note \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"ID": 123,
"Name": "Updated Title",
"Description": "Updated content..."
}'
Response
{
"ID": 123,
"Name": "Project Notes",
"Description": "This is the note content...",
...
}
Delete Note
Delete a note.
POST /v1/note/delete?Id={id}
Example
curl -X POST "http://localhost:8181/v1/note/delete?Id=123" \
-H "Accept: application/json"
Get Note Meta Keys
Get all unique metadata keys used across notes.
GET /v1/notes/meta/keys
Example
curl http://localhost:8181/v1/notes/meta/keys
Response
["attendees", "location", "priority", "status"]
Inline Editing
Edit note name or description with minimal payload.
Edit Name
POST /v1/note/editName?id={id}
Edit Description
POST /v1/note/editDescription?id={id}
Bulk Operations
Bulk operations apply an action to multiple notes at once. Each endpoint accepts a JSON or form-encoded body with ID (repeated) for the note IDs and EditedId (repeated) for the entity IDs to add or remove.
Add Tags
POST /v1/notes/addTags
| Parameter | Type | Description |
|---|---|---|
ID | integer[] | Note IDs to modify |
EditedId | integer[] | Tag IDs to add |
curl -X POST http://localhost:8181/v1/notes/addTags \
-H "Content-Type: application/json" \
-d '{
"ID": [1, 2, 3],
"EditedId": [10, 11]
}'
Remove Tags
POST /v1/notes/removeTags
| Parameter | Type | Description |
|---|---|---|
ID | integer[] | Note IDs to modify |
EditedId | integer[] | Tag IDs to remove |
curl -X POST http://localhost:8181/v1/notes/removeTags \
-H "Content-Type: application/json" \
-d '{
"ID": [1, 2, 3],
"EditedId": [10]
}'
Add Groups
POST /v1/notes/addGroups
| Parameter | Type | Description |
|---|---|---|
ID | integer[] | Note IDs to modify |
EditedId | integer[] | Group IDs to associate |
curl -X POST http://localhost:8181/v1/notes/addGroups \
-H "Content-Type: application/json" \
-d '{
"ID": [1, 2, 3],
"EditedId": [5]
}'
Add Metadata
POST /v1/notes/addMeta
| Parameter | Type | Description |
|---|---|---|
ID | integer[] | Note IDs to modify |
Meta | string | JSON metadata to merge (as a string) |
curl -X POST http://localhost:8181/v1/notes/addMeta \
-H "Content-Type: application/json" \
-d '{
"ID": [1, 2, 3],
"Meta": "{\"status\": \"reviewed\"}"
}'
Bulk Delete
POST /v1/notes/delete
| Parameter | Type | Description |
|---|---|---|
ID | integer[] | Note IDs to delete |
curl -X POST http://localhost:8181/v1/notes/delete \
-H "Content-Type: application/json" \
-d '{"ID": [1, 2, 3]}'
Note Sharing API
Share notes publicly via a unique token. Shared notes are accessible on the share server without authentication. See the Note Sharing feature docs for details.
Share a Note
Generate a public share token for a note.
POST /v1/note/share?noteId={id}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
noteId | integer | Required. The note ID to share |
Example
curl -X POST "http://localhost:8181/v1/note/share?noteId=123"
Response
{
"shareToken": "abc123def456ghi789jkl012mno345pq",
"shareUrl": "/s/abc123def456ghi789jkl012mno345pq"
}
The token is 32 characters. If the note is already shared, the existing token is returned.
Unshare a Note
Remove public access from a shared note.
DELETE /v1/note/share?noteId={id}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
noteId | integer | Required. The note ID to unshare |
Example
curl -X DELETE "http://localhost:8181/v1/note/share?noteId=123"
Response
{
"success": true
}
Note Blocks API
Blocks provide a structured editing system for note content. Each block has a type, position, content, and state. Content is what you edit in edit mode. State is what updates while viewing (e.g., checking a todo item). Blocks are ordered by position string, which uses fractional indexing for efficient reordering.
Block Types
Built-in block types:
| Type | Description |
|---|---|
text | Rich text content |
heading | Section heading (level 1-6) |
divider | Horizontal separator line |
gallery | Resource thumbnails in grid or list layout |
references | Linked group cards |
todos | Checklist with items |
table | Data table (manual data or query-based) |
calendar | Calendar view driven by ICS URLs, resources, and custom events |
Plugins can register additional block types with the prefix plugin:<plugin-name>:<type>.
Get Block Types
List all block types with their default content and state.
GET /v1/note/block/types
Example
curl http://localhost:8181/v1/note/block/types
Response
[
{
"type": "text",
"defaultContent": {"text": ""},
"defaultState": {}
},
{
"type": "heading",
"defaultContent": {"text": "", "level": 2},
"defaultState": {}
}
]
List Blocks for a Note
Retrieve all blocks for a specific note, ordered by position.
GET /v1/note/blocks?noteId={id}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
noteId | integer | Required. The note ID |
Example
curl "http://localhost:8181/v1/note/blocks?noteId=123"
Response
[
{
"id": 1,
"createdAt": "2024-01-15T10:00:00Z",
"updatedAt": "2024-01-15T10:30:00Z",
"noteId": 123,
"type": "heading",
"position": "a0",
"content": {"text": "Introduction", "level": 2},
"state": {}
},
{
"id": 2,
"createdAt": "2024-01-15T10:00:00Z",
"updatedAt": "2024-01-15T10:30:00Z",
"noteId": 123,
"type": "text",
"position": "a1",
"content": {"text": "This is the introduction paragraph..."},
"state": {}
}
]
Get Single Block
Retrieve a specific block by ID.
GET /v1/note/block?id={id}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | integer | Required. The block ID |
Example
curl "http://localhost:8181/v1/note/block?id=1"
Response
{
"id": 1,
"createdAt": "2024-01-15T10:00:00Z",
"updatedAt": "2024-01-15T10:30:00Z",
"noteId": 123,
"type": "text",
"position": "a0",
"content": {"text": "Hello world"},
"state": {}
}
Create Block
Create a new block for a note.
POST /v1/note/block
Request Body (JSON)
| Field | Type | Description |
|---|---|---|
noteId | integer | Required. The note ID |
type | string | Required. Block type (text, heading, etc.) |
position | string | Required. Position string for ordering |
content | object | Initial content (defaults to type's default content) |
Example
curl -X POST http://localhost:8181/v1/note/block \
-H "Content-Type: application/json" \
-d '{
"noteId": 123,
"type": "text",
"position": "a0",
"content": {"text": "My new paragraph"}
}'
Response
Returns the created block with HTTP status 201.
{
"id": 5,
"createdAt": "2024-01-15T12:00:00Z",
"updatedAt": "2024-01-15T12:00:00Z",
"noteId": 123,
"type": "text",
"position": "a0",
"content": {"text": "My new paragraph"},
"state": {}
}
Update Block Content
Update the content of an existing block. Use this in edit mode.
PUT /v1/note/block?id={id}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | integer | Required. The block ID |
Request Body (JSON)
| Field | Type | Description |
|---|---|---|
content | object | Required. New content for the block |
Example
curl -X PUT "http://localhost:8181/v1/note/block?id=5" \
-H "Content-Type: application/json" \
-d '{
"content": {"text": "Updated paragraph text"}
}'
Response
Returns the updated block.
{
"id": 5,
"createdAt": "2024-01-15T12:00:00Z",
"updatedAt": "2024-01-15T12:05:00Z",
"noteId": 123,
"type": "text",
"position": "a0",
"content": {"text": "Updated paragraph text"},
"state": {}
}
Update Block State
Update the state of a block. Use this while viewing (e.g., checking a todo item).
PATCH /v1/note/block/state?id={id}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | integer | Required. The block ID |
Request Body (JSON)
| Field | Type | Description |
|---|---|---|
state | object | Required. New state for the block |
Example
# Mark a todo item as checked
curl -X PATCH "http://localhost:8181/v1/note/block/state?id=10" \
-H "Content-Type: application/json" \
-d '{
"state": {"checked": ["item-1", "item-2"]}
}'
Response
Returns the updated block.
{
"id": 10,
"createdAt": "2024-01-15T12:00:00Z",
"updatedAt": "2024-01-15T12:10:00Z",
"noteId": 123,
"type": "todos",
"position": "a2",
"content": {"items": [{"id": "item-1", "text": "Task 1"}, {"id": "item-2", "text": "Task 2"}]},
"state": {"checked": ["item-1", "item-2"]}
}
Delete Block
Delete a block.
DELETE /v1/note/block?id={id}
Or using POST (for form compatibility):
POST /v1/note/block/delete?id={id}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | integer | Required. The block ID |
Example
curl -X DELETE "http://localhost:8181/v1/note/block?id=5"
Response
Returns HTTP status 204 (No Content) on success.
Reorder Blocks
Update positions for multiple blocks in a single request.
POST /v1/note/blocks/reorder
Request Body (JSON)
| Field | Type | Description |
|---|---|---|
noteId | integer | Required. The note ID |
positions | object | Required. Map of block ID to new position string |
Example
curl -X POST http://localhost:8181/v1/note/blocks/reorder \
-H "Content-Type: application/json" \
-d '{
"noteId": 123,
"positions": {
"1": "a0",
"2": "a1",
"3": "a2"
}
}'
Response
Returns HTTP status 204 (No Content) on success.
Rebalance Block Positions
Normalize position strings for all blocks in a note. Useful when position strings have grown too long from repeated insertions.
POST /v1/note/blocks/rebalance?noteId={id}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
noteId | integer | Required. The note ID |
Response
Returns HTTP status 204 (No Content) on success.
Get Table Block Query Data
Execute the query associated with a table block and return the results in table format.
GET /v1/note/block/table/query?blockId={blockId}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
blockId | integer | Required. The table block ID |
Additional query parameters are passed through to the query (merged with the block's stored queryParams).
Example
curl "http://localhost:8181/v1/note/block/table/query?blockId=10"
Response
{
"columns": [{"id": "name", "label": "name"}, {"id": "value", "label": "value"}],
"rows": [{"id": "row_0", "name": "Example", "value": 42}],
"cachedAt": "2024-01-15T10:00:00Z",
"queryId": 5,
"isStatic": false
}
Get Calendar Block Events
Get events for a calendar block within a date range.
GET /v1/note/block/calendar/events?blockId={blockId}&start={date}&end={date}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
blockId | integer | Required. The calendar block ID |
start | string | Required. Start date (YYYY-MM-DD) |
end | string | Required. End date (YYYY-MM-DD) |
Example
curl "http://localhost:8181/v1/note/block/calendar/events?blockId=15&start=2024-01-01&end=2024-01-31"
Block Type Schemas
Each block type has its own content and state schema.
Text Block
Content:
{
"text": "The text content"
}
State: Empty object {}
Heading Block
Content:
{
"text": "Heading text",
"level": 2
}
level: Integer 1-6 (corresponds to h1-h6)
State: Empty object {}
Divider Block
Content: Empty object {}
State: Empty object {}
Gallery Block
Content:
{
"resourceIds": [1, 2, 3]
}
resourceIds: Array of resource IDs to display
State:
{
"layout": "grid"
}
layout: Either"grid"or"list"
References Block
Content:
{
"groupIds": [10, 20, 30]
}
groupIds: Array of group IDs to display as references (required, can be empty)
State: Empty object {}
Todos Block
Content:
{
"items": [
{"id": "item-1", "label": "First task"},
{"id": "item-2", "label": "Second task"}
]
}
items: Array of todo items, each with uniqueidandlabel
State:
{
"checked": ["item-1"]
}
checked: Array of item IDs that are checked
Table Block
A table block holds either static data (columns/rows) or a query reference (queryId). It cannot have both.
Content (query-driven):
{
"queryId": 5,
"queryParams": {"minSize": "1000000"},
"isStatic": false
}
queryId: ID of a saved Query to executequeryParams: Named parameters to pass to the QueryisStatic: Set tofalsewhen using a query
Content (static data):
{
"columns": [{"id": "name", "label": "Name"}, {"id": "value", "label": "Value"}],
"rows": [{"name": "Example", "value": 42}]
}
columns: Array of column definitions (strings or objects withid/label)rows: Array of row objects keyed by column IDs
State:
{
"sortColumn": "Name",
"sortDir": "asc"
}
sortDir: Either"asc"or"desc"
Calendar Block
Content:
{
"calendars": [
{
"id": "work",
"name": "Work Calendar",
"color": "#3b82f6",
"source": {"type": "url", "url": "https://example.com/calendar.ics"}
},
{
"id": "local",
"name": "Stored Calendar",
"color": "#10b981",
"source": {"type": "resource", "resourceId": 42}
}
]
}
calendars: Array of calendar sources. Each entry has anid,name, optionalcolor(hex), and asourceobject withtype("url"or"resource") plus the correspondingurlorresourceIdfield.
State:
{
"view": "month",
"currentDate": "2024-06-15",
"customEvents": [
{
"id": "evt1",
"title": "Team Meeting",
"start": "2024-06-20T10:00:00Z",
"end": "2024-06-20T11:00:00Z",
"allDay": false,
"calendarId": "custom"
}
]
}
view:"month","week", or"agenda"currentDate: ISO date string for the current view positioncustomEvents: User-created events (max 500 per block, each withcalendarIdset to"custom")
Limitations:
- ICS responses are cached with a 30-minute TTL
- Maximum ICS file size: 10 MB
- No RRULE (recurring event) support -- only the first occurrence of recurring events is shown
Note Types API
Note types define templates and display customizations for notes.
List Note Types
Retrieve all note types.
GET /v1/note/noteTypes
Query Parameters
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
Name | string | Filter by name |
Description | string | Filter by description |
Example
curl http://localhost:8181/v1/note/noteTypes
Response
[
{
"ID": 1,
"Name": "Meeting",
"Description": "Meeting notes template",
"CustomHeader": "<h2>{{ note.Name }}</h2>",
"CustomSidebar": "...",
"CustomSummary": "...",
"CustomAvatar": "..."
}
]
Create Note Type
Create a new note type.
POST /v1/note/noteType
Parameters
| Parameter | Type | Description |
|---|---|---|
Name | string | Note type name |
Description | string | Description |
CustomHeader | string | Custom header template |
CustomSidebar | string | Custom sidebar template |
CustomSummary | string | Custom summary template |
CustomAvatar | string | Custom avatar template |
Example
curl -X POST http://localhost:8181/v1/note/noteType \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"Name": "Task",
"Description": "Task tracking notes",
"CustomHeader": "<div class=\"task-header\">{{ note.Name }}</div>"
}'
Edit Note Type
Update an existing note type.
POST /v1/note/noteType/edit
Parameters
Same as create, but include the ID field to identify which note type to update.
Example
curl -X POST http://localhost:8181/v1/note/noteType/edit \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"ID": 1,
"Name": "Meeting Notes",
"Description": "Updated description"
}'
Delete Note Type
Delete a note type.
POST /v1/note/noteType/delete?Id={id}
Example
curl -X POST "http://localhost:8181/v1/note/noteType/delete?Id=1" \
-H "Accept: application/json"
Inline Editing for Note Types
Edit Name
POST /v1/noteType/editName?id={id}
Edit Description
POST /v1/noteType/editDescription?id={id}