obsidian-local-rest-api

Obsidian Local REST API - Reference

Authentication

All endpoints (except GET /) require Bearer token authentication:

Authorization: Bearer <your-api-key>

Find the API key in Obsidian Settings > Plugins > Local REST API.

Base URL

  • HTTPS: https://127.0.0.1:27124 (self-signed cert)
  • HTTP: http://127.0.0.1:27123

The plugin generates a self-signed certificate on first run. The cert can be fetched from /obsidian-local-rest-api.crt.


Endpoints

System

Method Path Description
GET / Server status & auth check (no auth required)
GET /obsidian-local-rest-api.crt Returns the TLS certificate
GET /openapi.yaml Returns OpenAPI spec

GET / response:

{
  "authenticated": true,
  "ok": "OK",
  "service": "Obsidian Local REST API",
  "versions": { "obsidian": "...", "self": "..." }
}

Vault File Operations (/vault/{filename})

Method Path Description
GET /vault/{filename} Read file content
PUT /vault/{filename} Create or overwrite file
POST /vault/{filename} Append content to file
PATCH /vault/{filename} Partially update content (heading/block/frontmatter targeting)
DELETE /vault/{filename} Delete file
GET /vault/ List files in vault root
GET /vault/{dirpath}/ List files in directory (trailing slash = directory)

GET (read file):

  • Default Accept: returns raw markdown (text/markdown)
  • Accept: application/vnd.olrapi.note+json: returns JSON with parsed frontmatter, tags, stats
  • Accept: application/vnd.olrapi.document-map+json: returns headings, block refs, frontmatter fields

NoteJson schema:

{
  "content": "string (markdown)",
  "frontmatter": {},
  "path": "string",
  "stat": { "ctime": 0, "mtime": 0, "size": 0 },
  "tags": ["string"]
}

GET (directory listing):

  • Returns {"files": [{"path": "…", "stat": {…}}]}

PUT (create/overwrite):

  • Body: file content
  • Content-Type: text/markdown for notes
  • If-None-Match: * header: only create if file doesn't exist (returns 412 if it does)

POST (append):

  • Body: content to append
  • Content-Type: text/markdown
  • Content is appended to end of file

DELETE:

  • Returns 204 on success, 404 if not found

PATCH Operations (Surgical Edits)

The PATCH method enables targeted content modifications within a note.

Required Headers:

Header Values Description
Operation append, prepend, replace What to do
Target-Type heading, block, frontmatter What kind of target
Target string The specific target (heading path, block ref ID, frontmatter field name)

Optional Headers:

Header Default Description
Target-Delimiter :: Separator for nested headings (e.g., Heading 1::Subheading)
Trim-Target-Whitespace false Trim whitespace from target
Create-Target-If-Missing false Create the target if it doesn't exist

Examples:

Append under a heading:

PATCH /vault/path/to/note.md
Operation: append
Target-Type: heading
Target: Heading 1::Subheading 1:1:1
Content-Type: text/markdown

Hello

Replace a frontmatter field:

PATCH /vault/path/to/note.md
Operation: replace
Target-Type: frontmatter
Target: status
Content-Type: application/json

"done"

Append to block reference:

PATCH /vault/path/to/note.md
Operation: append
Target-Type: block
Target: 2d9b4a
Content-Type: text/markdown

New content here

Active File Operations (/active/)

Same methods as vault files (GET, PUT, POST, PATCH, DELETE) but operates on the currently open file in Obsidian. No {filename} parameter needed.


Periodic Notes (/periodic/{period}/)

Method Path Description
GET/PUT/POST/PATCH/DELETE /periodic/{period}/ Current period's note
GET/PUT/POST/PATCH/DELETE /periodic/{period}/{year}/{month}/{day}/ Specific date's note

{period} values: daily, weekly, monthly, quarterly, yearly

Same request/response semantics as vault file operations.


Search

Simple Search:

POST /search/simple/?query=search+terms

Returns matching filenames with context snippets.

Response:

[
  {
    "filename": "path/to/note.md",
    "score": 0.95,
    "matches": [{ "match": { "start": 0, "end": 10 }, "context": "..." }]
  }
]

Structured Search:

POST /search/
Content-Type: application/vnd.olrapi.dataview.dql+txt

TABLE file.name, file.mtime FROM "folder" WHERE contains(tags, "#coffee")

Or with JsonLogic:

POST /search/
Content-Type: application/vnd.olrapi.jsonlogic+json

{"and": [{"glob": [{"var": "path"}, "daily/*"]}]}

Commands

Method Path Description
GET /commands/ List all available commands
POST /commands/{commandId}/ Execute a command

GET /commands/ response:

{
  "commands": [
    { "id": "global-search:open", "name": "Search: Search in all files" },
    { "id": "graph:open", "name": "Graph view: Open graph view" }
  ]
}

Tags

Method Path Description
GET /tags/ List all tags with usage counts

Open File in Obsidian UI

POST /open/{filename}?newLeaf=true

Opens the specified file in Obsidian's interface. Creates the file if it doesn't exist.


Error Responses

All errors return:

{
  "errorCode": 40149,
  "message": "A brief description of the error."
}

Error codes are 5-digit numbers unique to each error type.


Key Endpoints for Pour

Based on the project spec, these are the most relevant endpoints:

  1. GET / - Check if API is available (connectivity test)
  2. PUT /vault/{filename} - Create new notes (coffee logs, music sets)
  3. PATCH /vault/{filename} - Append under headers (journal entries)
  4. GET /vault/{dirpath}/ - List files in directory (populate dynamic dropdowns)
  5. POST /search/ - Dataview queries for dynamic selects by tag