Ledger
A structured credit and cash ledger. Organize entries into monthly draft periods, review evidence, and complete periods with the owner's confirmation.
An API-first workspace for agents
The main interface is /api. Read the OpenAPI contract
for available actions, input schemas and the ledger workflow.
This document exposes tools and a JavaScript client for interacting with Ledger. Usage is fully headless: actions return data; they do not navigate, render results or change the document. Do not wait for UI changes to confirm an operation.
Choose your interface
1. WebMCP, when supported
Use your browser or harness's tool discovery to find this document's registered Ledger tools: nine ledger actions and four authentication actions. If none appear, check whether your harness already offers another browser connection with WebMCP support. Otherwise, use the JavaScript fallback.
The tools expose the same actions as the API. The browser attaches the session cookie automatically; tool results never include a session credential. Tool registration alone does not sign you in.
2. JavaScript fallback
If native tools are unavailable, use your harness's browser JavaScript execution facility.
Call window.LedgerApi.describe() for descriptions and named input schemas.
The fallback and native tools use the same cookie-authenticated client.
await window.LedgerApi.getSession({});
await window.LedgerApi.listAccounts({});
If there is no valid session, use the email login flow below.
3. Direct HTTP
If browser access is read-only and WebMCP is unavailable, use an HTTP-capable tool.
Request a code through /api/auth/request, then explicitly choose
sessionMode: "token" on /api/auth/exchange. That mode returns
accessToken without setting a cookie. Send it as Authorization: Bearer <accessToken>
for session, logout and ledger operations. Keep it in protected execution storage rather than logs or model context.
Authenticate with email
- Check
getSession({})first. Reuse an existing valid session instead of requesting another code. - If authentication is required, call
requestLoginCode({email})and keep its returnedchallengeId. The same flow handles signup and login. - Retrieve the email using an authorized mailbox tool, or ask the user for the six-digit code. It is sent by Ledger <login@auth.mzmz.cl>. Check spam if it does not appear.
- Call
exchangeLoginCode({challengeId, code}). The browser client establishes the session and returns identity and expiry, not the credential.
Codes expire in ten minutes, permit three failed attempts, and can be exchanged only once. Wait at least 60 seconds before requesting another email and respect rate-limit responses. An email request alone does not authenticate you.
const challenge = await window.LedgerApi.requestLoginCode({email: 'you@example.com'});
// Obtain the matching code through an authorized mailbox tool or the user.
await window.LedgerApi.exchangeLoginCode({
challengeId: challenge.challengeId,
code: 'received-six-digit-code'
});
await window.LedgerApi.listAccounts({});
Credential handling
Sessions last up to 24 hours. Browser authentication uses a host-only HttpOnly Secure
SameSite=Strict cookie. Reuse the same browser context/profile to retain authentication
across reloads. A fresh context may require another login. Call logout({})
to revoke the current session.
The browser client does not expose the session credential to document JavaScript or tool results. Privileged browser tooling may still inspect cookies or network traffic. Codes are transient inputs; harnesses may record tool arguments, so avoid unnecessary exposure. For direct HTTP, use protected credential storage and opaque execution rather than printing tokens or response headers.
Working with the ledger
- Preserve bank descriptions and evidence. Propose classifications, distinguish uncertainty, and obtain user approval before persisting changes.
- Use confirmed mutation responses; read back when uncertainty or a checkpoint requires it.
- After timeout or cancellation, inspect state before repeating a write. Cancellation is not rollback. Login exchange is single-use and must not be retried automatically.