Skip to main content

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

ParameterTypeDescription
pageintegerPage number (default: 1)
NamestringFilter by name (partial match)
DescriptionstringFilter by description (partial match)
OwnerIdintegerFilter by owner group ID
Groupsinteger[]Filter by associated group IDs
Tagsinteger[]Filter by tag IDs
Idsinteger[]Filter by specific note IDs
NoteTypeIdintegerFilter by note type ID
CreatedBeforestringFilter by creation date (ISO 8601)
CreatedAfterstringFilter by creation date (ISO 8601)
StartDateBeforestringNotes starting before this date
StartDateAfterstringNotes starting after this date
EndDateBeforestringNotes ending before this date
EndDateAfterstringNotes ending after this date
SharedbooleanPresence flag for shared notes. Include this parameter (for example Shared=1) to return only notes that have a share token.
MetaQuerystring[]Filter by metadata conditions (key:value or key:OP:value)
SortBystring[]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

ParameterTypeDescription
IDintegerNote ID (include to update, omit to create)
NamestringNote title
DescriptionstringNote content/body
OwnerIdintegerOwner group ID
NoteTypeIdintegerNote type ID
Groupsinteger[]Associated group IDs
Tagsinteger[]Tag IDs
Resourcesinteger[]Associated resource IDs
MetastringJSON metadata object
StartDatestringStart date (ISO 8601)
EndDatestringEnd 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
ParameterTypeDescription
IDinteger[]Note IDs to modify
EditedIdinteger[]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
ParameterTypeDescription
IDinteger[]Note IDs to modify
EditedIdinteger[]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
ParameterTypeDescription
IDinteger[]Note IDs to modify
EditedIdinteger[]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
ParameterTypeDescription
IDinteger[]Note IDs to modify
MetastringJSON 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
ParameterTypeDescription
IDinteger[]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

ParameterTypeDescription
noteIdintegerRequired. 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

ParameterTypeDescription
noteIdintegerRequired. 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:

TypeDescription
textRich text content
headingSection heading (level 1-6)
dividerHorizontal separator line
galleryResource thumbnails in grid or list layout
referencesLinked group cards
todosChecklist with items
tableData table (manual data or query-based)
calendarCalendar 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

ParameterTypeDescription
noteIdintegerRequired. 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

ParameterTypeDescription
idintegerRequired. 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)

FieldTypeDescription
noteIdintegerRequired. The note ID
typestringRequired. Block type (text, heading, etc.)
positionstringRequired. Position string for ordering
contentobjectInitial 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

ParameterTypeDescription
idintegerRequired. The block ID

Request Body (JSON)

FieldTypeDescription
contentobjectRequired. 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

ParameterTypeDescription
idintegerRequired. The block ID

Request Body (JSON)

FieldTypeDescription
stateobjectRequired. 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

ParameterTypeDescription
idintegerRequired. 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)

FieldTypeDescription
noteIdintegerRequired. The note ID
positionsobjectRequired. 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

ParameterTypeDescription
noteIdintegerRequired. 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

ParameterTypeDescription
blockIdintegerRequired. 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

ParameterTypeDescription
blockIdintegerRequired. The calendar block ID
startstringRequired. Start date (YYYY-MM-DD)
endstringRequired. 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 {}

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 unique id and label

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 execute
  • queryParams: Named parameters to pass to the Query
  • isStatic: Set to false when 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 with id/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 an id, name, optional color (hex), and a source object with type ("url" or "resource") plus the corresponding url or resourceId field.

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 position
  • customEvents: User-created events (max 500 per block, each with calendarId set 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

ParameterTypeDescription
pageintegerPage number (default: 1)
NamestringFilter by name
DescriptionstringFilter 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

ParameterTypeDescription
NamestringNote type name
DescriptionstringDescription
CustomHeaderstringCustom header template
CustomSidebarstringCustom sidebar template
CustomSummarystringCustom summary template
CustomAvatarstringCustom 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}