All tags endpoints require authentication via JWT or API token.
Bearer token (JWT or API token)
Create Tag
Create a new tag for organizing notes.
curl -X POST http://localhost:3001/api/tags \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Work",
"color": "#3B82F6"
}'
Tag name (must be unique per user, cannot be empty)
{
"id" : "tag-uuid-123" ,
"name" : "Work" ,
"color" : "#3B82F6" ,
"isDeleted" : false ,
"createdAt" : "2026-03-02T10:30:00.000Z" ,
"updatedAt" : "2026-03-02T10:30:00.000Z" ,
"userId" : "user-uuid-456"
}
Error Responses
{
"statusCode" : 409 ,
"message" : "Tag with this name already exists" ,
"error" : "Conflict"
}
Retrieve all tags for the current user (excluding deleted tags).
curl -X GET http://localhost:3001/api/tags \
-H "Authorization: Bearer YOUR_TOKEN"
[
{
"id" : "tag-uuid-123" ,
"name" : "Work" ,
"color" : "#3B82F6" ,
"isDeleted" : false ,
"createdAt" : "2026-03-02T10:30:00.000Z" ,
"updatedAt" : "2026-03-02T10:30:00.000Z" ,
"userId" : "user-uuid-456"
},
{
"id" : "tag-uuid-789" ,
"name" : "Personal" ,
"color" : "#10B981" ,
"isDeleted" : false ,
"createdAt" : "2026-03-01T09:00:00.000Z" ,
"updatedAt" : "2026-03-01T09:00:00.000Z" ,
"userId" : "user-uuid-456"
},
{
"id" : "tag-uuid-321" ,
"name" : "Important" ,
"color" : "#EF4444" ,
"isDeleted" : false ,
"createdAt" : "2026-02-28T15:00:00.000Z" ,
"updatedAt" : "2026-02-28T15:00:00.000Z" ,
"userId" : "user-uuid-456"
}
]
Get Tag
Retrieve a single tag by ID.
curl -X GET http://localhost:3001/api/tags/tag-uuid-123 \
-H "Authorization: Bearer YOUR_TOKEN"
{
"id" : "tag-uuid-123" ,
"name" : "Work" ,
"color" : "#3B82F6" ,
"isDeleted" : false ,
"createdAt" : "2026-03-02T10:30:00.000Z" ,
"updatedAt" : "2026-03-02T10:30:00.000Z" ,
"userId" : "user-uuid-456"
}
Error Responses
{
"statusCode" : 404 ,
"message" : "Tag not found" ,
"error" : "Not Found"
}
Update Tag
Update tag name and/or color.
curl -X PATCH http://localhost:3001/api/tags/tag-uuid-123 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Work Projects",
"color": "#2563EB"
}'
Updated tag color (hex code)
{
"id" : "tag-uuid-123" ,
"name" : "Work Projects" ,
"color" : "#2563EB" ,
"isDeleted" : false ,
"createdAt" : "2026-03-02T10:30:00.000Z" ,
"updatedAt" : "2026-03-02T11:00:00.000Z" ,
"userId" : "user-uuid-456"
}
Error Responses
{
"statusCode" : 409 ,
"message" : "Tag with this name already exists" ,
"error" : "Conflict"
}
Delete Tag
Soft-delete a tag. Notes associated with the tag will remain but the tag will be marked as deleted.
curl -X DELETE http://localhost:3001/api/tags/tag-uuid-123 \
-H "Authorization: Bearer YOUR_TOKEN"
{
"id" : "tag-uuid-123" ,
"name" : "Work" ,
"color" : "#3B82F6" ,
"isDeleted" : true ,
"createdAt" : "2026-03-02T10:30:00.000Z" ,
"updatedAt" : "2026-03-02T12:00:00.000Z" ,
"userId" : "user-uuid-456"
}
Deleted tags are soft-deleted (marked as isDeleted: true) but remain in the database. They are excluded from list and get operations.
Get Notes by Tag
Retrieve all notes associated with a specific tag.
curl -X GET http://localhost:3001/api/tags/tag-uuid-123/notes \
-H "Authorization: Bearer YOUR_TOKEN"
[
{
"id" : "note-uuid-1" ,
"title" : "Project Planning" ,
"content" : "Q2 roadmap and milestones" ,
"isPinned" : true ,
"isArchived" : false ,
"background" : null ,
"state" : "active" ,
"createdAt" : "2026-03-02T10:00:00.000Z" ,
"updatedAt" : "2026-03-02T10:30:00.000Z" ,
"userId" : "user-uuid-456" ,
"tags" : [
{
"id" : "tag-uuid-123" ,
"name" : "Work" ,
"color" : "#3B82F6"
},
{
"id" : "tag-uuid-789" ,
"name" : "Planning" ,
"color" : "#8B5CF6"
}
],
"isOwner" : true ,
"permission" : null
},
{
"id" : "note-uuid-2" ,
"title" : "Team Meeting" ,
"content" : "Weekly sync notes" ,
"isPinned" : false ,
"isArchived" : false ,
"background" : "#E0F2FE" ,
"state" : "active" ,
"createdAt" : "2026-03-01T14:00:00.000Z" ,
"updatedAt" : "2026-03-01T15:00:00.000Z" ,
"userId" : "user-uuid-456" ,
"tags" : [
{
"id" : "tag-uuid-123" ,
"name" : "Work" ,
"color" : "#3B82F6"
}
],
"isOwner" : true ,
"permission" : null
}
]
This endpoint returns only active (non-trashed, non-archived) notes. Use the notes endpoint with tagId query parameter for more control.
Advanced endpoint for offline-first clients to synchronize local tag changes with the server.
curl -X POST http://localhost:3001/api/tags/sync \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"lastSyncedAt": "2026-03-02T10:00:00.000Z",
"changes": [
{
"id": "tag-uuid-local-1",
"name": "New Tag",
"color": "#F59E0B",
"updatedAt": "2026-03-02T11:00:00.000Z"
},
{
"id": "tag-uuid-123",
"name": "Work Projects",
"color": "#2563EB",
"updatedAt": "2026-03-02T11:30:00.000Z"
},
{
"id": "tag-uuid-999",
"name": "Old Tag",
"isDeleted": true,
"updatedAt": "2026-03-02T12:00:00.000Z"
}
]
}'
ISO 8601 timestamp of last sync (optional for initial sync)
Array of tag changes to sync (optional)
Show Change Object Fields
Tag UUID (can be client-generated)
ISO 8601 timestamp of change
{
"serverTags" : [
{
"id" : "tag-uuid-456" ,
"name" : "Server Tag" ,
"color" : "#6366F1" ,
"isDeleted" : false ,
"createdAt" : "2026-03-02T10:45:00.000Z" ,
"updatedAt" : "2026-03-02T10:45:00.000Z" ,
"userId" : "user-uuid-456"
}
],
"conflicts" : [
{
"clientTag" : {
"id" : "tag-uuid-123" ,
"name" : "Work Projects" ,
"updatedAt" : "2026-03-02T11:30:00.000Z"
},
"serverTag" : {
"id" : "tag-uuid-123" ,
"name" : "Work Items" ,
"updatedAt" : "2026-03-02T11:45:00.000Z"
}
}
]
}
Tags modified on server since lastSyncedAt
Tags with conflicting changes requiring conflict resolution
The sync endpoint handles three-way merge logic. Conflicts occur when the same tag is modified both locally and on the server. Client should resolve conflicts by choosing client, server, or merged version.
Tag Naming Rules
Tag names must be unique per user
Tag names are case-sensitive
Empty names are not allowed
Leading/trailing whitespace is preserved
Special characters are allowed
Tag colors should be specified as hex codes:
{
"color" : "#3B82F6" // Valid
}
Omitting the color field will store null:
{
"color" : null // No color specified
}