1. Base URL and auth
Base URL: https://harken.hemisthia.com/api/v5.
Send Authorization: Bearer hk_… for an API key, a signed-in native Harken session, or a Better Auth OAuth 2.1 access token. The OAuth resource and token audience must be exactly https://harken.hemisthia.com/api/v5. Grants issued for /mcp will not authenticate; reauthorize those clients against /api/v5.
Protected-resource metadata is served by the API at /.well-known/oauth-protected-resource and /.well-known/oauth-protected-resource/api/v5.
List keys with notes:read. Issue and revoke keys only from a signed-in native Harken session. Keys never expire; revoke them to stop authentication. The secret is shown once.
curl -sS https://harken.hemisthia.com/api/v5/notes \
-H "Authorization: Bearer hk_…" \
-H "Accept: application/json"
2. Permissions
API keys use these existing scopes: notes:read, notes:write, notes:delete, meetings:read, assets:read, assets:write. External OAuth grants notes:read, notes:write, notes:delete, meetings:read, and offline_access only; it cannot grant asset scopes. Start with read-only access.
GET /api/v5/health is public. Authenticated GET /api/v5/export skips the paid-entitlement gate. Other /api/v5 routes require an active Harken Pro entitlement after authentication.
3. Pagination and Markdown
List and search responses use owner-bound cursors except transcripts, which use offset/nextOffset. Default page size is 50; maximum 200. Tampered cursors return 400 invalid_cursor. Search returns results: [{ note, snippet }], not a bare notes array.
GET /api/v5/notes/{id} returns JSON by default. Send Accept: text/markdown for the body with YAML front-matter and the same ETag.
4. Version conflicts and idempotency
Reads and mutations that carry a resource version return a quoted ETag. PATCH, DELETE, restore, and asset writes require If-Match. Missing → 428. Stale → 412 version_conflict with the current resource inlined. Transcript append and API-key issue/revoke do not use If-Match.
Every mutation requires Idempotency-Key, including API-key issue and revoke. The same owner, operation, key, and body replays the original response. A different body with the same key returns 409 idempotency_key_reuse. API-key issuance replays omit the secret.
5. Changes, assets, and export
GET /api/v5/changes?since=genesis starts the feed. Pass the returned cursor as since afterwards. include=bodies inlines note and collection bodies when they fit.
Upload assets with multipart field asset and the note ETag. Download bytes at GET /api/v5/assets/{assetID} (hash ETag). Pass meta=1 for JSON metadata whose version ETag is required to delete. Export is GET /api/v5/export (zip, one request per 10 minutes per owner).
6. What this API is not
This is not an MCP server. Dictation, recording controls, owner/admin routes, and other app features are not part of /api/v5.