Notes
Create, list, update, and delete notes. Attach notes to CRM records, control visibility, and use @mentions to notify teammates.
Notes let your team capture context about contacts, companies, and opportunities. Each note supports rich HTML content, can be linked to one or more CRM records, and respects visibility rules so private notes stay private.
List Notes
GET /api/v1/notesReturns a paginated list of notes. Visibility filtering is applied automatically: you will see workspace-visible notes and your own private notes.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
entity_type | string | -- | Filter by linked entity type: contacts, companies, opportunities |
entity_id | string | -- | Filter by linked entity ID |
filters | string | -- | JSON-encoded FilterGroup for advanced filtering |
sort | string | -- | JSON array for multi-field sorting. When provided, sort_by and sort_dir are ignored. |
sort_by | string | created_at | Single field to sort by (used only when sort is absent or not valid JSON) |
sort_dir | string | desc | Sort direction: asc or desc (used only with sort_by) |
cursor | string | -- | Pagination cursor from a previous response |
limit | number | 20 | Number of results per page (max 100) |
Example: Notes for a Contact
curl -X GET "https://kasar.app/api/v1/notes?entity_type=contacts&entity_id=a1b2c3d4-e5f6-7890-abcd-ef0123456789" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..." \
-H "Content-Type: application/json"Response:
{
"data": [
{
"id": "b2c3d4e5-f6a7-8901-bcde-f01234567890",
"title": "Call summary - contract renewal",
"content": "<p>Alice confirmed she wants to renew for 2 years. Needs updated pricing by Friday.</p>",
"visibility": "workspace",
"created_by_display": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"display": "Marc Dupont",
"image": "https://lh3.googleusercontent.com/a/photo.jpg"
},
"created_at": "2025-03-12T16:45:00Z",
"updated_at": "2025-03-12T16:45:00Z"
}
],
"total": 4
}The response is { "data": [...], "total": <int> }, plus a nextCursor string when more pages remain. On the last page (no more results) nextCursor is omitted entirely. Pass it back as the cursor query parameter to fetch the next page.
Each note includes a created_by_display object with the author's name and avatar, ready for display in your UI.
Example: All Notes
curl -X GET "https://kasar.app/api/v1/notes?limit=50&sort_dir=desc" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..."Create a Note
POST /api/v1/notesCreates a new note. If an entity context is provided, a many-to-many link is created automatically.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
content | string | Yes | HTML content of the note |
entity_type | string | No | Entity type to link a single record: contacts, companies, opportunities |
entity_id | string | No | Entity ID to link (used with entity_type) |
linked_entities | array | No | Link multiple records at once: array of { id, type } objects (combined with entity_type/entity_id if both are given) |
mentioned_user_ids | array | No | Array of workspace user UUIDs to notify as @mentions (see Mentions) |
data | object | No | Additional metadata |
data.visibility | string | No | workspace or private. Defaults to private when omitted. |
Example
curl -X POST "https://kasar.app/api/v1/notes" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"content": "<p>Alice confirmed she wants to renew for 2 years. Needs updated pricing by Friday.</p>",
"entity_type": "contacts",
"entity_id": "a1b2c3d4-e5f6-7890-abcd-ef0123456789",
"data": {
"visibility": "workspace"
}
}'Response (201):
{
"note_id": "b2c3d4e5-f6a7-8901-bcde-f01234567890",
"action": "created"
}The note title is auto-generated from the HTML content. You do not need to provide it manually.
To notify teammates, pass their workspace user IDs explicitly in mentioned_user_ids. Mentions are not parsed from the HTML content — only the IDs you supply trigger notifications. See the Mentions section for details.
Update a Note
PUT /api/v1/notes/{id}Updates the content or linked entities of an existing note. Only include the fields you want to change.
Request Body
| Field | Type | Description |
|---|---|---|
content | string | Updated HTML content. When provided, the auto-generated title is regenerated. |
linked_entities | array | Replace linked entities with this list of { id, type } objects. Omit to leave existing links untouched. |
data | object | Additional fields to update |
data.visibility | string | workspace or private. Optional — omitting it keeps the note's current visibility. |
Only the fields you include are changed. Omitting data.visibility (or omitting data entirely) leaves the existing visibility in place.
Example: Update Content
curl -X PUT "https://kasar.app/api/v1/notes/b2c3d4e5-f6a7-8901-bcde-f01234567890" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"content": "<p>Alice confirmed renewal for 2 years. Updated pricing sent on March 14.</p>"
}'Response:
{
"note_id": "b2c3d4e5-f6a7-8901-bcde-f01234567890",
"action": "updated"
}Example: Link to Multiple Entities
curl -X PUT "https://kasar.app/api/v1/notes/b2c3d4e5-f6a7-8901-bcde-f01234567890" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"linked_entities": [
{ "id": "a1b2c3d4-e5f6-7890-abcd-ef0123456789", "type": "contacts" },
{ "id": "c3d4e5f6-a7b8-9012-cdef-012345678901", "type": "opportunities" }
]
}'Passing linked_entities replaces all existing many-to-many links. To keep current links, include them in the array alongside any new ones.
When content is updated, the auto-generated title is regenerated to reflect the new content.
Delete a Note
DELETE /api/v1/notes/{id}Permanently deletes a note and removes all entity links.
Example
curl -X DELETE "https://kasar.app/api/v1/notes/b2c3d4e5-f6a7-8901-bcde-f01234567890" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..."Response (200):
{
"deleted": true
}Mentions
Notes support @mentions to notify workspace users. Mentions are explicit only — the API does not parse them from the note's HTML content. To notify teammates, pass an array of their workspace user UUIDs in mentioned_user_ids. Each listed user receives a mention_in_note notification.
The note's author is automatically excluded from notifications (you will not notify yourself).
Mentions are sent on note creation only. Pass mentioned_user_ids in the POST /api/v1/notes body; the field is not read by the update endpoint.
Example: Explicit Mentions
curl -X POST "https://kasar.app/api/v1/notes" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"content": "<p>Discussed pricing with the team. Need input from sales.</p>",
"mentioned_user_ids": [
"550e8400-e29b-41d4-a716-446655440000",
"660f9511-f30c-52e5-b827-557766551111"
]
}'Visibility
Notes support two visibility levels:
| Visibility | Description |
|---|---|
workspace | Visible to all members of the workspace. |
private | Visible only to the note's author. This is the default when data.visibility is omitted. |
The API enforces visibility automatically on list requests. You will never see another user's private notes in API responses.
Error Responses
Errors are returned with HTTP 400 and a flat error body ({ code, message, ... }) — there is no "error": true envelope.
Note Not Found
{
"code": "RECORD_NOT_FOUND",
"message": "Note 'b2c3d4e5-f6a7-8901-bcde-f01234567890' not found."
}Missing Content
{
"code": "MISSING_REQUIRED_FIELD",
"message": "content is required."
}