Skip to content

Latest commit

Β 

History

History
916 lines (732 loc) Β· 16 KB

File metadata and controls

916 lines (732 loc) Β· 16 KB

πŸ“‘ API Documentation

Base URL: http://localhost:9000

All protected endpoints require authentication when authentication.enabled: true in config.yaml.


πŸ” Authentication

Login Page

GET /login

Returns the HTML login page.

Login

POST /login
Content-Type: application/json

{
  "password": "your_password"
}

Authenticates the user session.

Response:

{
  "success": true,
  "message": "Login successful"
}

Logout

POST /logout

Logs out the current user session.


πŸ—‚οΈ Notes

List All Notes

GET /api/notes

Returns all notes with their metadata and folder structure.

Response:

{
  "notes": [
    {
      "path": "folder/note.md",
      "name": "note",
      "folder": "folder",
      "title": "Note Title",
      "created_at": "2025-11-26T10:30:00Z",
      "updated_at": "2025-11-26T11:00:00Z"
    }
  ]
}

Get Note Content

GET /api/notes/{note_path}

Retrieve the content of a specific note.

Example:

curl http://localhost:9000/api/notes/folder/mynote.md

Response:

{
  "success": true,
  "path": "folder/mynote.md",
  "content": "# My Note\nContent here..."
}

Create/Update Note

POST /api/notes/{note_path}
Content-Type: application/json

{
  "content": "# My Note\nNote content here..."
}

Response:

{
  "success": true,
  "path": "test.md",
  "message": "Note created/updated successfully",
  "content": "# My Note\nNote content here..."
}

Linux/Mac:

curl -X POST http://localhost:9000/api/notes/test.md \
  -H "Content-Type: application/json" \
  -d '{"content": "# Hello World"}'

Windows PowerShell:

curl.exe -X POST http://localhost:9000/api/notes/test.md -H "Content-Type: application/json" -d "{\"content\": \"# Hello World\"}"

Delete Note

DELETE /api/notes/{note_path}

Example:

curl -X DELETE http://localhost:9000/api/notes/test.md

Move Note

POST /api/notes/move
Content-Type: application/json

{
  "oldPath": "note.md",
  "newPath": "folder/note.md"
}

Response:

{
  "success": true,
  "message": "Note moved successfully"
}

🎬 Media

Get Media

GET /api/media/{media_path}

Retrieve a media file (image, audio, video, PDF) with authentication protection.

Example:

curl http://localhost:9000/api/media/folder/_attachments/image-20240417093343.png

Security Note: This endpoint requires authentication and validates that:

  • The media path is within the notes directory (prevents directory traversal)
  • The file exists and is a valid media format
  • The requesting user is authenticated (if auth is enabled)

Upload Media

POST /api/upload-media
Content-Type: multipart/form-data

file: <media file>
note_path: <path of note to attach to>

Upload a media file to the _attachments directory. Files are automatically organized per-folder and named with timestamps to prevent conflicts.

Supported formats & size limits:

Type Formats Max Size
Images JPG, PNG, GIF, WebP 10 MB
Audio MP3, WAV, OGG, M4A 50 MB
Video MP4, WebM, MOV, AVI 100 MB
Documents PDF 20 MB

Response:

{
  "success": true,
  "path": "folder/_attachments/media-20240417093343.png",
  "filename": "media-20240417093343.png",
  "message": "Media uploaded successfully"
}

Example (using curl):

curl -X POST http://localhost:9000/api/upload-media \
  -F "file=@/path/to/file.mp3" \
  -F "note_path=folder/mynote.md"

Windows PowerShell:

curl.exe -X POST http://localhost:9000/api/upload-media -F "file=@C:\path\to\video.mp4" -F "note_path=folder/mynote.md"

Move Media

POST /api/media/move
Content-Type: application/json

{
  "oldPath": "_attachments/image.png",
  "newPath": "folder/_attachments/image.png"
}

Move a media file to a different location. Supports drag & drop in the UI.

Response:

{
  "success": true,
  "message": "Media moved successfully",
  "newPath": "folder/_attachments/image.png"
}

List Orphaned Media

GET /api/media/orphaned

Lists media files that are not referenced by any notes (dangling attachments).

Response:

{
  "success": true,
  "files": [
    {
      "path": "folder/_attachments/old-image.png",
      "size": 102400,
      "modified": "2025-11-25T10:30:00Z"
    }
  ],
  "count": 1
}

Cleanup Orphaned Media

DELETE /api/media/orphaned

Deletes all orphaned media files. Returns summary of deleted files.

Response:

{
  "success": true,
  "deleted_count": 5,
  "freed_space_bytes": 1048576,
  "message": "Cleaned up 5 orphaned files"
}

Rate Limit: 30 requests per 60 seconds


πŸ“ Folders

Create Folder

POST /api/folders
Content-Type: application/json

{
  "path": "Projects/2025"
}

Response:

{
  "success": true,
  "message": "Folder created successfully"
}

Rate Limit: 30 requests per 60 seconds

Delete Folder

DELETE /api/folders/{folder_path}

Deletes a folder and all its contents.

Example:

curl -X DELETE http://localhost:9000/api/folders/Projects/Archive

Rate Limit: 20 requests per 60 seconds

Move Folder

POST /api/folders/move
Content-Type: application/json

{
  "oldPath": "OldFolder",
  "newPath": "NewFolder"
}

Response:

{
  "success": true,
  "message": "Folder moved successfully"
}

Rate Limit: 20 requests per 60 seconds

Rename Folder

POST /api/folders/rename
Content-Type: application/json

{
  "oldPath": "Projects",
  "newName": "Work"
}

Response:

{
  "success": true,
  "message": "Folder renamed successfully"
}

Rate Limit: 30 requests per 60 seconds


πŸ” Search

Search Notes

GET /api/search?q={query}

Optional query parameters:

  • q - Search query (required)
  • page - Page number (default: 1)
  • per_page - Results per page (default: 50)

Example:

curl "http://localhost:9000/api/search?q=hello&page=1&per_page=20"

Response:

{
  "query": "hello",
  "results": [
    {
      "path": "folder/note.md",
      "title": "Hello World",
      "snippet": "...<mark>hello</mark> world...",
      "score": 1.234
    }
  ],
  "total": 10,
  "page": 1,
  "per_page": 20,
  "pages": 1
}

Rate Limit: 60 requests per 60 seconds


🏷️ Tags

List All Tags

GET /api/tags

Returns all tags found in notes with their usage counts.

Response:

{
  "tags": {
    "python": 5,
    "tutorial": 3,
    "backend": 2
  }
}

Get Notes by Tag

GET /api/tags/{tag_name}

Returns all notes that have a specific tag.

Response:

{
  "tag": "python",
  "notes": [
    {
      "path": "tutorials/python-basics.md",
      "name": "python-basics",
      "folder": "tutorials",
      "tags": ["python", "tutorial"]
    }
  ]
}

πŸ“„ Templates

List Templates

GET /api/templates

Returns all available note templates from the _templates folder.

Rate Limit: 120 requests per 60 seconds

Response:

{
  "templates": [
    {
      "name": "meeting-notes",
      "path": "_templates/meeting-notes.md",
      "modified": "2025-11-26T10:30:00"
    },
    {
      "name": "daily-journal",
      "path": "_templates/daily-journal.md",
      "modified": "2025-11-26T10:25:00"
    }
  ]
}

Get Template Content

GET /api/templates/{template_name}

Returns the content of a specific template.

Parameters:

  • template_name - Template name (without .md extension)

Response:

{
  "name": "meeting-notes",
  "content": "# Meeting Notes\n\nDate: {{date}}\nAttendees: {{attendees}}\n..."
}

Rate Limit: 120 requests per 60 seconds

Create Note from Template

POST /api/templates/create-note
Content-Type: application/json

{
  "templateName": "meeting-notes",
  "notePath": "meetings/weekly-sync.md"
}

Creates a new note from a template with placeholder replacement.

Supported placeholders:

  • {{date}} - Current date (YYYY-MM-DD)
  • {{time}} - Current time (HH:MM:SS)
  • {{datetime}} - Current datetime
  • {{timestamp}} - Unix timestamp
  • {{year}} - Current year (YYYY)
  • {{month}} - Current month (MM)
  • {{day}} - Current day (DD)
  • {{title}} - Note name without extension
  • {{folder}} - Parent folder name

Response:

{
  "success": true,
  "path": "meetings/weekly-sync.md",
  "message": "Note created from template successfully",
  "content": "# Meeting Notes\n\nDate: 2025-11-26\nAttendees: \n..."
}

Rate Limit: 60 requests per 60 seconds


πŸ”— Sharing

Share notes publicly without requiring authentication.

Create Share Link

POST /api/share/{note_path}
Content-Type: application/json

{
  "theme": "dracula"
}

Creates a share token for the note. The theme is optional (defaults to "light").

Response:

{
  "success": true,
  "token": "LRFEo86oSVeJ3Gju",
  "url": "http://localhost:9000/share/LRFEo86oSVeJ3Gju",
  "note_path": "folder/note.md"
}

Rate Limit: 30 requests per 60 seconds

Get Share Status

GET /api/share/{note_path}

Check if a note is currently shared.

Response:

{
  "shared": true,
  "token": "LRFEo86oSVeJ3Gju",
  "url": "http://localhost:9000/share/LRFEo86oSVeJ3Gju",
  "theme": "dracula",
  "created": "2026-01-15T10:30:00+00:00"
}

Rate Limit: 120 requests per 60 seconds

Revoke Share

DELETE /api/share/{note_path}

Removes public access to the note.

Response:

{
  "success": true,
  "message": "Share revoked"
}

Rate Limit: 30 requests per 60 seconds

List Shared Notes

GET /api/shared-notes

Returns paths of all currently shared notes.

Response:

{
  "paths": ["folder/note.md", "another.md"]
}

Rate Limit: 60 requests per 60 seconds

View Shared Note (Public)

GET /share/{token}

Public endpoint - no authentication required. Returns the note as a standalone HTML page with the theme set when sharing was created. Optionally generate QR code for mobile access.

Example:

curl http://localhost:9000/share/LRFEo86oSVeJ3Gju

πŸ”— Backlinks

Find all notes that link to a specific note using wikilink syntax [[link]] and markdown links.

Get Backlinks

GET /api/backlinks/{note_path}

Returns source notes and where they link to the target note.

Response:

{
  "success": true,
  "backlinks": [
    {
      "source_path": "other-note.md",
      "link_texts": ["note-name", "folder/note"],
      "links": [
        {
          "line": 10,
          "context": "See also [[note-name]]",
          "type": "wikilink"
        },
        {
          "line": 15,
          "context": "Check [this](folder/note) out",
          "type": "markdown"
        }
      ]
    }
  ],
  "count": 1
}

Rate Limit: 60 requests per 60 seconds


πŸ“Š Statistics

Get comprehensive statistics for a note including word count, reading time, and structure analysis.

Get Note Statistics

GET /api/stats/{note_path}

Response:

{
  "success": true,
  "data": {
    "words": 150,
    "sentences": 12,
    "characters": 800,
    "total_characters": 1000,
    "reading_time_minutes": 1,
    "lines": 50,
    "paragraphs": 10,
    "list_items": 5,
    "tables": 1,
    "links": 8,
    "internal_links": 6,
    "external_links": 2,
    "wikilinks": 3,
    "code_blocks": 2,
    "inline_code": 5,
    "headings": {
      "h1": 1,
      "h2": 3,
      "h3": 2
    },
    "tasks": {
      "total": 4,
      "completed": 2,
      "pending": 2
    },
    "images": 1,
    "blockquotes": 2
  }
}

Rate Limit: 60 requests per 60 seconds


🎨 Themes

List Themes

GET /api/themes

Returns all available themes from the themes directory.

Get Theme CSS

GET /api/themes/{theme_id}

Returns the CSS content for the specified theme.

Example:

curl http://localhost:9000/api/themes/dark

🌍 Locales

List Available Languages

GET /api/locales

Returns all available locale (translation) files.

Get Locale File

GET /api/locales/{language_code}

Returns locale content for the specified language (e.g., en-US, zh-CN).


πŸ“‘ WebSocket

Real-time Updates

GET /ws

WebSocket endpoint for receiving real-time notifications. When authentication is enabled, requires valid session.

Events:

  • notes_updated - Broadcast when background note scan completes (new/updated/deleted notes detected)

Example message:

{
  "event": "notes_updated",
  "timestamp": "2025-11-26T11:00:00Z"
}

βš™οΈ System

Get Config

GET /api/config

Returns application configuration (may filter sensitive fields like secret_key).

Response:

{
  "app": {
    "name": "GoNote",
    "version": "0.25.0"
  },
  "server": {
    "host": "0.0.0.0",
    "port": 9000,
    "debug": false
  },
  "authentication": {
    "enabled": false
  },
  "search": {
    "enabled": true
  }
}

Rate Limit: 120 requests per 60 seconds

Health Check

GET /health

Returns system health status.

Response:

{
  "status": "healthy",
  "timestamp": "2025-11-26T11:00:00Z",
  "version": "0.25.0"
}

πŸ”’ Security Headers

GoNote includes the following security middleware:

  • CSRF Protection: Double Submit Cookie pattern applied to state-changing operations
  • Rate Limiting: Per-endpoint rate limits to prevent abuse
  • CORS: Configurable allowed origins
  • Secure Cookies: Automatically enabled when HTTPS detected

CSRF Token: The CSRF token is set in a cookie named csrf_. For state-changing requests, include the token in the X-CSRF-Token header. The token is readable by JavaScript (HTTPOnly=false) to facilitate this.


πŸ“ Response Format

All endpoints return JSON responses:

Success (generic):

{
  "success": true,
  "data": { ... }
}

Success (specific): Some endpoints use custom response structures tailored to their data (see individual endpoint docs).

Error:

{
  "detail": "Error message"
}

πŸ”’ Rate Limiting

Global Rate Limiter

A global rate limiter is applied to all requests. The default configuration (when RATE_LIMIT_ENABLED=true) is:

  • 30 requests per 1 second window

Configure via:

rate_limit:
  enabled: true
  max_requests: 30
  window_seconds: 1

Or environment variables:

RATE_LIMIT_ENABLED=true
RATE_LIMIT_MAX=30
RATE_LIMIT_WINDOW=1

Per-Endpoint Rate Limiting

Some endpoints have custom limits:

Endpoint Limit Window
POST /login 10 60s
POST /api/notes/move 30 60s
DELETE /api/notes/* 30 60s
POST /api/folders 30 60s
POST /api/folders/rename 30 60s
POST /api/share/* 30 60s
DELETE /api/share/* 30 60s
POST /api/media/move 30 60s
POST /api/upload-media 20 60s
POST /api/templates/create-note 60 60s
GET /api/backlinks/* 60 60s
GET /api/stats/* 60 60s
GET /api/shared-notes 60 60s
GET /api/templates 120 60s
GET /api/templates/* 120 60s
GET /api/share/* 120 60s
GET /api/config 120 60s

When rate limit is exceeded, server returns 429 Too Many Requests.


πŸ’‘ Usage Tips

  • Use /api/config to discover current runtime configuration (except secrets)
  • All responses are case-sensitive; use snake_case for field names
  • For drag & drop media uploads, the note_path parameter indicates which note the media is attached to
  • All paths are URL-encoded and case-sensitive
  • When authentication is enabled, include session cookies in requests (browser handles this automatically; for API calls, ensure you're logged in)

Tip: For password-protected deployments, log in first via POST /login to obtain session cookies, then all /api/* endpoints will be accessible.