Local API Reference
The Claspt desktop app answers a local HTTP API on 127.0.0.1 for the browser
extension, the bundled MCP server, the claspt command and any script on the
same machine. This page covers the rules that apply to every route. The routes
themselves live in one place:
- The API Explorer shows every route with its parameters, schemas, responses and a curl example. It is generated from the OpenAPI document, and a test in the repository fails when the app’s route table and the document differ, so it is always the current description.
- /openapi.yaml is the document itself, for any tool that reads OpenAPI 3.1.
The explorer cannot send requests: the app answers loopback requests only and refuses browser origins other than the Claspt extension. Copy the curl example instead.
Basics
Section titled “Basics”| Base URL | http://127.0.0.1:9315 (the port is in Settings › Integrations › Local API) |
| Authentication | Authorization: Bearer <key> on every request |
| Transport | Plain HTTP over loopback. Nothing listens on any other interface. |
| Bodies | JSON, except 204 No Content |
| Feature detection | GET /api/status returns a features map. Check it rather than comparing versions. |
Surfaces
Section titled “Surfaces”| Surface | Who uses it | Sees |
|---|---|---|
| Local API (this page) | The extension, the MCP server, the CLI, scripts on the same machine | Decrypted pages and secret blocks, subject to scope and approval |
| MCP server | AI tools | The same local API, with the same key, scope, approval, rate limit and log |
| Claspt Sync (Pro) | Other desktops and the phone | Encrypted content only. It has no page or secret operations. |
The phone has no local API; it reads the vault through Claspt Sync.
Keys and scopes
Section titled “Keys and scopes”Every client has its own key, issued once and stored as a hash. Three ways to get one:
claspt mcp install <tool>for an AI tool: one shared key for the tools on this machine, or--separatefor a key of the tool’s own.- Pair another browser in the app, for the extension.
- Settings › Integrations › API Clients, for a script.
The prefix names the scope:
| Prefix | Scope | Pages, memory, search | Secret values | Secret writes | Approval |
|---|---|---|---|---|---|
clsn_ | Notes | Read and write | Redacted | Refused | Never |
clss_ | Secrets | Read and write | Decrypted | Allowed | As set in the app |
clsp_ is an older spelling of a Secrets key and is still accepted. Keys are
compared in constant time. Pick the narrowest scope that does the job.
Errors
Section titled “Errors”Every error is a JSON envelope:
{ "error": { "code": "NOT_FOUND", "message": "Page not found: credentials/missing.md", "details": { "path": "credentials/missing.md" } }}| Status | Code | Meaning |
|---|---|---|
| 400 | BAD_REQUEST | Malformed body, invalid query, unknown enum value |
| 400 | INVALID_PATH | The path climbs out of the vault (..) or is absolute |
| 401 | UNAUTHORIZED | No key, or a key the open vault does not know. Run claspt mcp doctor. |
| 403 | VAULT_LOCKED | The vault is locked, or the key lock is on. Unlock the app. |
| 403 | SCOPE_INSUFFICIENT | A Notes key asked for a secret value or a secret write |
| 403 | APPROVAL_DENIED | The owner declined, or did not answer within 30 seconds |
| 403 | PAIRING_CLOSED | Pairing is not open in the app |
| 404 | NOT_FOUND | No such page, folder or memory |
| 404 | BLOCK_NOT_FOUND | No secret block with that label on the page |
| 409 | LABEL_CONFLICT | Another block on the page already has the requested label |
| 412 | PRECONDITION_FAILED | If-Match did not match. Fetch again and retry. |
| 503 | NOT_READY | The search index is still being built |
| 500 | INTERNAL_ERROR | Encryption, file or index failure |
details is optional and route-specific. A few older responses that the
envelope does not cover are plain text with the same status.
Identifiers
Section titled “Identifiers”A page is addressed by path or by id, in the same place in the URL:
- Path, relative to the vault, such as
credentials/2026-04-26-103000-github.md. Stable until the page is moved or renamed. Slashes are encoded so the path fits one URL segment:credentials%2F2026-04-26-103000-github.md. - Id, the UUID in the page’s front matter. Stable across moves and renames. Use it when the reference is stored somewhere else.
Concurrency
Section titled “Concurrency”Responses that return a page carry an ETag. It is the page’s updated_at
instant, so two clients can compare it without identical file bytes.
| Write | Behaviour |
|---|---|
Without If-Match | Last write wins |
With If-Match: <etag> | Refused with 412 PRECONDITION_FAILED if the page changed in between. Fetch again and retry. |
The extension sends If-Match on every edit and undoes its optimistic change
on a 412.
Approval, brake and log
Section titled “Approval, brake and log”A Secrets-scope read asks the owner in the app, naming the client and the page. The answer can be:
| Answer | Covers |
|---|---|
| Once | This request only |
| Until lock | Every Secrets-scope request from any client until the vault locks |
| Always | This client and this page, until revoked in Settings |
The request waits up to 30 seconds for an answer; silence is a refusal. Notes-scope requests never ask. Whether a Secrets key asks at all is the access mode in Settings; a Secrets key with approval off reads without a prompt, so give one only to a tool you trust.
Each client may decrypt at most 15 secrets a minute to start. Every request is
recorded with the client’s name in Settings › Activity and with
claspt log; values are never logged. A write that carries a recognisable key
outside a secret block is refused.
For the tool-facing view of all this, see AI tools: credentials.
Secrets by reference
Section titled “Secrets by reference”Listings hand back claspt://secret/<page>?block=<label>#<field> addresses
beside every field, so a tool can pass a secret to claspt run or
claspt inject without ever holding the value.
Source
Section titled “Source”The app is source-available under the PolyForm Shield licence at
github.com/Indivar/claspt-apps. The
OpenAPI document is docs/api/openapi.yaml there, next to the test that holds
it to the route table.