HTTP API guide
macOS · Premium · Updated 2026-09-17
Let local scripts read a Secret text value or file from the current Vault by Key. HTTP API requires LockMemo Premium on macOS. iOS and Android can create and view Secrets, but do not run the API service.
https://127.0.0.1:494431. Set up access
- Unlock LockMemo and wait for the initial sync. In Memos, add a Secret with
Key = demo.api-keyand text Valueexample-value. Keys are case-sensitive and must be unique across all Secrets in the current Vault. - Open Settings → Sync → HTTP API. Copy the Access token, then press Start access.
- After the first start, open ⋮ → Client configuration and choose Export public CA. Save it as
lockmemo-local-ca.pemin Downloads, or adjust the example path. - Run the commands below in a terminal on the same Mac. The setup reads the token you just copied using
pbpaste, so you do not need to paste the token into your shell history.
LOCKMEMO_CA="$HOME/Downloads/lockmemo-local-ca.pem"
LOCKMEMO_TOKEN="$(pbpaste)"
This is HTTPS, using the local CA exported by the app. The examples verify it with --cacert; you do not need to install it as a system-wide trusted CA or bypass verification with -k.
2. cURL examples
Check service status
curl --noproxy '*' --http1.1 --silent --show-error --fail \
--cacert "$LOCKMEMO_CA" \
https://127.0.0.1:49443/v1/status
{"service":"lockmemo","apiVersion":1,"state":"active"}
This endpoint needs no token and returns no Secrets. When the service is stopped, the connection normally fails instead of returning status JSON.
Read text
printf 'Authorization: Bearer %s\n' "$LOCKMEMO_TOKEN" |
curl --noproxy '*' --http1.1 --silent --show-error --fail \
--cacert "$LOCKMEMO_CA" \
--header @- \
--header 'Content-Type: application/json' \
--data-binary '{"key":"demo.api-key"}' \
https://127.0.0.1:49443/v1/resolve
The successful response is the raw UTF-8 bytes of example-value, with no JSON wrapper or added newline. --header @- reads the Authorization header from standard input.
Read a file
Add another entry, demo.config, and use the paperclip to select a test JSON file. This command writes or replaces demo-config.json in the current directory; use a dedicated test directory.
umask 077
printf 'Authorization: Bearer %s\n' "$LOCKMEMO_TOKEN" |
curl --noproxy '*' --http1.1 --silent --show-error --fail \
--cacert "$LOCKMEMO_CA" \
--header @- \
--header 'Content-Type: application/json' \
--data-binary '{"key":"demo.config"}' \
--output ./demo-config.json \
https://127.0.0.1:49443/v1/resolve
Text and files use the same endpoint. A file returns its original bytes, not a filename or Base64. The client chooses the output filename. When finished, clear the token variable from this shell:
unset LOCKMEMO_TOKEN
3. Python example
With Python 3 installed, this script needs no third-party libraries. Paste the token at the hidden prompt. It writes the successful response to standard output; replace that line with your own processing if needed.
import getpass
import json
from pathlib import Path
import ssl
import sys
import urllib.error
import urllib.request
ca_file = Path.home() / "Downloads" / "lockmemo-local-ca.pem"
context = ssl.create_default_context(cafile=str(ca_file))
token = getpass.getpass("LockMemo access token: ")
request = urllib.request.Request(
"https://127.0.0.1:49443/v1/resolve",
data=json.dumps({"key": "demo.api-key"}).encode("utf-8"),
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
},
method="POST",
)
# Keep loopback requests direct, even when a proxy is configured.
opener = urllib.request.build_opener(
urllib.request.ProxyHandler({}),
urllib.request.HTTPSHandler(context=context),
)
try:
with opener.open(request, timeout=30) as response:
sys.stdout.buffer.write(response.read())
except urllib.error.HTTPError as error:
print(f"HTTP {error.code}: {error.read().decode('utf-8')}", file=sys.stderr)
raise SystemExit(1)
except urllib.error.URLError:
print("Check LockMemo access, the local CA file, and the endpoint.", file=sys.stderr)
raise SystemExit(1)
4. API reference
| Endpoint | Purpose |
|---|---|
GET /v1/status | Read service status; no authentication required. |
POST /v1/resolve | Authenticate with a Bearer token and send {"key":"demo.api-key"}. |
- Send
Authorization: Bearer <token>andContent-Type: application/json. The body must contain exactly onekeyfield, not a Memo title. - A successful response is
application/octet-stream: only the Value, with no Key, Notes, Memo title, or attachment metadata. There is no list, bulk-export, or write endpoint. - Request bodies are limited to 4 KiB and each Value to 10 MiB. Authenticated reads are limited to 60 per minute; queue and connection limits also apply.
- The listener is IPv4 loopback-only and uses HTTP/1.1. Chunked requests and browser Origin headers are rejected. Use local scripts, not web-page JavaScript, another computer, or a phone.
5. Tokens and lifecycle
- While running, access includes every Secret in the current Vault, including later additions. Regular Memos, Vault credentials, and Codes are excluded. A local program holding the token can read these Secrets while access is running.
- The 43-character secure random token is stored only on this device, outside Vault Git sync. Stop/start, unlocking, and app restarts keep it unchanged. Only an explicit, confirmed Update replaces an existing token.
- Updating the token stops access and invalidates the old token. Update your script, then start access again. After rotating the local CA, export it again and update the certificate file your script uses.
- There is no session countdown. Access stops on manual stop, Vault lock, sleep, app exit, or loss of Premium. Unlocking does not automatically restart it.
- Open Access log from the settings page. Logs stay on this device and retain at most 500 entries from the last 7 days. Keep tokens and Secret values out of code repositories and build logs.
6. Troubleshooting
| Result | What to check |
|---|---|
400 · invalid_request | Check the method, path, JSON, and Content-Type; send exactly one key field. |
401 · invalid_token | The token is missing, malformed, or invalid. Copy the current token and include the space after Bearer. |
404 · secret_not_available | Check the exact case-sensitive Key and whether it exists in the current Vault. |
423 · access_inactive | Unlock the correct Vault, wait for sync, and press Start access. |
429 · rate_limited | Reduce request frequency or concurrency and retry later. |
500 · resolution_failed | Retry after sync or editing finishes. If persistent, check duplicate Keys, missing attachments, or Vault consistency. |
Connection failure: confirm the app is open and unlocked, HTTP API shows Running, and port 49443 is free. Locking, a write pause, or connection limits can close the connection without a JSON error. Certificate error: use the current CA exported by this Mac and keep HTTPS verification enabled.