10 KiB
Goldbrain — Obsidian Local REST API Reference
Server: https://goldbrainapi.mpm.to (reverse proxy → Obsidian Local REST API on 192.168.86.15:27124)
Auth header: Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8
The endpoint has a valid TLS certificate — -k is not required. Paths address the vault at its root.
Prefer
scripts/goldbrain.shover the raw recipes below. It wraps every verb with auth, status checking, retry, idempotent append, and frontmatter patches. The recipes here are the underlying mechanics and the fallback. If you callcurldirectly, check the HTTP status — add-o /dev/null -w "%{http_code}"and branch on it. APATCHto a non-existent heading returns400 invalid-target(errorCode 40080) and the write is silently lost; a barecurlthat ignores status will report success anyway.GETreturns404for a missing file. Treat any>= 400as a failed operation, surface it, and do not continue as if it succeeded.
Reading Files
# Read any file by vault path
curl -s \
-H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \
"https://goldbrainapi.mpm.to/vault/_agent/context/current-context.md"
Returns raw file content (text/markdown). On 404, the file does not exist.
# Read a specific heading's content only
curl -s \
-H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \
"https://goldbrainapi.mpm.to/vault/_agent/memory/semantic/operator-preferences.md/heading/Operator"
Nested headings: separate levels with :: (URL-encode spaces as %20):
/vault/path/to/note.md/heading/Work%3A%3AMeetings
Listing Directories
# List contents of a directory (trailing slash required)
curl -s \
-H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \
"https://goldbrainapi.mpm.to/vault/_agent/sessions/"
Returns JSON: { "files": [...], "folders": [...] }.
Appending Content (POST)
POST appends to the end of an existing file. Creates the file if it doesn't exist.
cat > /tmp/obs_entry.md << 'OBSEOF'
- 2026-06-05: your entry here
OBSEOF
curl -s -X POST \
-H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \
-H "Content-Type: text/markdown" \
--data-binary @/tmp/obs_entry.md \
"https://goldbrainapi.mpm.to/vault/inbox/captures/inbox.md"
Creating or Overwriting Files (PUT)
PUT creates a new file or fully overwrites an existing one. Intermediate directories are created automatically.
cat > /tmp/obs_file.md << 'OBSEOF'
---
type: session-log
status: complete
created: 2026-06-05
updated: 2026-06-05
tags: [agent, session]
agent_written: true
source_notes: []
---
# content here
## Related
- [[projects/active/some-project]]
OBSEOF
curl -s -X PUT \
-H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \
-H "Content-Type: text/markdown" \
--data-binary @/tmp/obs_file.md \
"https://goldbrainapi.mpm.to/vault/_agent/sessions/2026-06-05-1430-my-session.md"
Patching a Specific Section (PATCH)
PATCH edits inside a file without rewriting it. Target and operation are set via headers.
Append under a heading
Heading targets must be the FULL heading path, ::-delimited from the top-level heading. A bare subheading name returns 400 invalid-target (errorCode 40080). Example: ## Fact / Pattern nested under # Operator Preferences → Target: Operator Preferences::Fact / Pattern. Percent-encode non-ASCII characters (e.g. H%C3%A9llo); spaces are fine.
Special characters in heading targets (em dashes, parentheses) — known failure. The server matches the
Targetheader against heading text only after URL-decoding it, and the matcher applies regex-special handling to characters like()[]. A heading such as# EarthDnD — Personal Projecttargeted literally fails withinvalid-target(40080), because the raw em dash (—, U+2014) rides unreliably in an HTTP header. Handle it in this priority order:
- Prevent — keep new headings ASCII. When you author a heading you might later PATCH, use a plain hyphen with spaces (
-), never an em dash/en dash, and avoid parentheses/brackets.# EarthDnD - Personal Projectis always PATCH-safe. This is the durable fix.- Percent-encode the offending run when targeting an existing special-char heading: em dash
—→%E2%80%94, en dash–→%E2%80%93. Example fixing the bug-report case:Target: EarthDnD %E2%80%94 Personal Project::AI Platform Roles.- Fallback (GET → edit → PUT) when even encoding fails (e.g. parentheses): read the whole file, edit the section in memory, PUT it back. Atomic, not in-place — small race-condition risk on hot files, so prefer fixing the heading to ASCII.
| Character | Glyph | Percent-encoding |
|---|---|---|
| Em dash | — (U+2014) |
%E2%80%94 |
| En dash | – (U+2013) |
%E2%80%93 |
| Space | |
%20 (literal space also works) |
:: (nesting, in URL path only) |
:: |
%3A%3A |
| é (example accented char) | é |
%C3%A9 |
cat > /tmp/obs_patch.md << 'OBSEOF'
Bryan prefers concise status updates - lead with the decision.
OBSEOF
curl -s -X PATCH \
-H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \
-H "Operation: append" \
-H "Target-Type: heading" \
-H "Target: Operator Preferences::Fact / Pattern" \
-H "Content-Type: text/markdown" \
--data-binary @/tmp/obs_patch.md \
"https://goldbrainapi.mpm.to/vault/_agent/memory/semantic/operator-preferences.md"
Discover heading / block / frontmatter targets
When unsure of the exact heading path, GET the note with the document-map Accept header:
curl -s \
-H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \
-H "Accept: application/vnd.olrapi.document-map+json" \
"https://goldbrainapi.mpm.to/vault/_agent/memory/semantic/operator-preferences.md"
Returns { "headings": [...], "blocks": [...], "frontmatterFields": [...] }. Copy the heading string verbatim into Target.
Replace a heading's content entirely
Same call with Operation: replace — e.g. to refresh a project's Project Name::Status.
Prepend under a heading
Same call with Operation: prepend.
Patch a frontmatter field
curl -s -X PATCH \
-H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \
-H "Operation: replace" \
-H "Target-Type: frontmatter" \
-H "Target: updated" \
-H "Content-Type: application/json" \
--data '"2026-06-05"' \
"https://goldbrainapi.mpm.to/vault/projects/active/vault-foundation.md"
Searching
curl -s -X POST \
-H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \
"https://goldbrainapi.mpm.to/search/simple/?query=weekly+review"
Returns an array of { filename, score, matches: [{ context, match }] }.
Deleting Files
curl -s -X DELETE \
-H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \
"https://goldbrainapi.mpm.to/vault/inbox/imports/old-note.md"
Only on explicit operator request. Deletion is destructive.
URL-Encoding Notes
- Path separators (
/) in the vault path are literal — do not encode them. - Spaces in filenames or heading targets in a URL: use
%20. - Nested heading levels in a URL path: use
%3A%3Afor::. - Heading text in the
Target:header: the full heading path joined by::(e.g.Operator Preferences::Fact / Pattern), no#; spaces are fine; percent-encode non-ASCII.
Memory Routing Map
| Situation | Vault path | Method |
|---|---|---|
| Quick capture / unsorted | inbox/captures/inbox.md (date-prefixed line) |
POST |
| Raw imported material | inbox/imports/ |
PUT |
| Operator preference / durable fact | _agent/memory/semantic/operator-preferences.md |
PATCH |
| Other durable facts, patterns | _agent/memory/semantic/<slug>.md |
PUT |
| Event record (what happened) | _agent/memory/episodic/<slug>.md |
PUT |
| Short-lived, time-boxed state | _agent/memory/working/<slug>.md |
PUT |
| Task-scoped context / focus | _agent/context/current-context.md |
PATCH / PUT |
| Working-session log | _agent/sessions/YYYY-MM-DD-HHMM-<slug>.md |
PUT |
| Long-running project state | projects/<lifecycle>/<slug>.md (lifecycle: incubating → active → on-hold/archived; folder and status: MUST agree) |
PUT + PATCH |
| Ongoing area of responsibility (standing domain, no end state) | areas/<domain>/<slug>.md (<domain>: business/personal/learning/systems) |
PUT |
| Non-obvious decision (ADR) | decisions/by-date/YYYY-MM-DD-<slug>.md (mirror only into an existing project note's ## Key Decisions; otherwise skip) |
PUT |
| Person context | resources/people/<name>.md |
PUT / PATCH |
| Company / organization context | resources/companies/<slug>.md |
PUT / PATCH |
| Concept / reference note | resources/concepts/ or resources/references/ |
PUT |
| Meeting notes / call recap | resources/meetings/YYYY-MM-DD-<slug>.md |
PUT |
| Skill / plugin capability entry (catalog, not build work) | _agent/skills/active/<slug>.md (→ archived/ when retired) |
PUT |
| Daily activity / Agent Log | journal/daily/YYYY-MM-DD.md |
POST / PATCH |
| Journal rollup | journal/{weekly/YYYY-Www,monthly/YYYY-MM,quarterly/YYYY-Qn,annual/YYYY}.md (weekly = opt-in on first session of a new ISO week; monthly = offered with Vault Health; quarterly/annual = manual) |
PUT |
| Vault-health audit (agent self-maintenance) | _agent/health/YYYY-MM-vault-health.md (monthly; NOT a journal entry) |
PUT |
| Session-end orientation pointer | _agent/heartbeat/last-session.md (one line, overwritten each session end) |
PUT |
| Bootstrap marker (plugin-owned) | _agent/goldbrain-vault.md (schema_version, bootstrap date) — the "is this vault set up?" probe |
GET / PUT |
Slug rules: kebab-case, ASCII, ~40 chars max. Every file carries canonical frontmatter (see vault-layout.md).