# Proof Entry An agent-first ledger for freelancers and small businesses: money out and money in. Logging defaults to pending proposals, excluded from totals. Agents and scripts can directly add complete structured data using add_income/add_expense or explicitly confirm new entries using confirm: true on log tools or HTTP POST. Confirmed entries count immediately. Hosted chat, receipt and email extraction remain pending until reviewed. ## Endpoints - MCP server (streamable HTTP): https://staging.glidzr.com/api/mcp - HTTP API: https://staging.glidzr.com/api/transactions (GET, POST) - OAuth discovery: https://staging.glidzr.com/.well-known/oauth-authorization-server - Protected resource metadata: https://staging.glidzr.com/.well-known/oauth-protected-resource ## Documentation - MCP setup: https://staging.glidzr.com/agents/mcp - Device-code authorization (CLI/agents): https://staging.glidzr.com/agents/device - Tool catalog and input schemas: https://staging.glidzr.com/agents/tools - HTTP API guide: https://staging.glidzr.com/agents/http - OpenAPI (bearer-token transaction API): https://staging.glidzr.com/openapi.json - MCP server card: https://staging.glidzr.com/.well-known/mcp/server-card.json ## Authentication OAuth 2.1 with PKCE and dynamic client registration. Point an MCP client at the endpoint and it can walk the whole flow itself; an unauthenticated request answers 401 with a WWW-Authenticate header naming the discovery document above. Bearer writes default to pending. Explicit confirm: true writes complete structured data as confirmed. A signed-in human session retains the form contract. Device-code authorization (RFC 8628) is available for public device clients. Discover device_authorization_endpoint and use the standard device grant at token_endpoint. Register a public client with token_endpoint_auth_method=none, the device and optional refresh_token grants, and response_types=[] (or omitted). Generic native redirect_uris are discarded and returned as []; application_type and other unsupported metadata are ignored. No callback is used for device flow. Code issuance and token polling accept form encoding or JSON. Optional resource must match the protected-resource metadata value https://staging.glidzr.com; other targets return invalid_target. Device refresh accepts that same resource. A signed-in human must match the code and explicitly approve. Device tokens retain all agent restrictions and never grant a browser session. Codes last 600 seconds; polling starts at 5 seconds and slow_down adds 5 seconds. Use https://staging.glidzr.com/app/device to approve codes or revoke device connections. Google recovery of an unverified account revokes previous sessions and agent credentials. Reconnect through OAuth for a new token. The tenant and ledger stay the same; receipt forwarding uses a new address from Settings. Requests can return 429 before authentication; honor Retry-After when present. MCP/HTTP calls share limits of 120 per user and 600 per IP per minute. MCP batches contain at most 20 calls and each call counts. JSON bodies are capped at 64 KiB. HTTP and MCP list limits must be integers from 1 to 200 (default 50 if omitted). Invalid HTTP limits return 400; invalid MCP limits return an ok:false tool result. ## Rules that hold everywhere - Money crosses the wire as integer minor units with an explicit currency exponent and a preformatted string. Never assume two decimal places: exponents differ (JPY 0, AED 2, KWD 3). - Amounts are always positive strings, transcribed exactly as printed or as the user said them. Never do arithmetic on money. `direction` ("expense" | "income") carries the sign and defaults to expense when omitted. - Foreign-currency proposals cannot be confirmed without an exchange rate a human supplies. Do not invent one. ## Structured entry POST /api/transactions with confirm: true records income or expense directly. MCP add_income/add_expense accept confirm: true or false, defaulting to true. Pass false to create a pending proposal. log_income/log_expense also accept both values but default to false. Confirmed writes require description, positive decimal string amount, currency and a real yyyy-mm-dd occurredAt date. Confirmed money/rates use decimal strings without grouping or currency symbols. Foreign currency requires a supplied fxRate to the ledger base currency. Invalid tax, references and line items are rejected. Unknown fields, confidence and projectId are rejected for confirmed writes. Confirmation is never inferred from completeness or confidence. Repeated successful calls create separate entries; there is no idempotency key. These calls create new entries, not confirmation by existing ID. ## MCP tools ### list_transactions (read-only) List ledger entries, newest first — expenses, income, or both. Returns amounts as integer minor units alongside the currency exponent — never divide by 100 without checking it. Amounts are always positive; read `direction` to know which way the money went. Defaults to confirmed entries only; pending ones are unreviewed proposals and are excluded from every total. ### get_totals (read-only) Totals for a period: money in, money out, and the net between them, plus the VAT position and what is still unbilled to clients. Counts confirmed entries only. ### totals_by_category (read-only) Confirmed totals grouped by category for a period, largest first. Defaults to expenses; pass direction to break income down instead. ### list_categories (read-only) The category vocabulary for this ledger, split by which side it belongs to. Use these slugs verbatim when logging; an unrecognised slug — or one from the wrong side — is dropped rather than created. ### log_expense (write — pending-or-confirmed) Propose money SPENT. Defaults to PENDING, excluded from totals. Pass confirm: true only to explicitly record complete structured data. Confirmed writes require description, positive string amount, currency and yyyy-mm-dd date, plus fxRate for foreign currency. Transcribe supplied amounts and rates; never invent them. ### log_income (write — pending-or-confirmed) Propose money RECEIVED. Defaults to PENDING, excluded from totals. Pass confirm: true only to explicitly record complete structured data. Confirmed writes require description, positive string amount, currency and yyyy-mm-dd date, plus fxRate for foreign currency. Transcribe supplied amounts and rates; never invent them. ### add_expense (write — confirmed-by-default) Add money SPENT. confirm defaults to true: records complete structured data immediately and includes it in totals. Pass confirm: false to create a pending proposal instead. Confirmed writes require description, positive string amount, currency and yyyy-mm-dd date, plus fxRate for foreign currency. Transcribe supplied amounts and rates; never invent them. ### add_income (write — confirmed-by-default) Add money RECEIVED. confirm defaults to true: records complete structured data immediately and includes it in totals. Pass confirm: false to create a pending proposal instead. Confirmed writes require description, positive string amount, currency and yyyy-mm-dd date, plus fxRate for foreign currency. Transcribe supplied amounts and rates; never invent them. ### list_pending_review (read-only) Entries captured automatically that are waiting for the account holder to confirm or reject. These are excluded from all totals. ### list_recurring (read-only) Standing instructions that write to this ledger on a schedule — rent, retainers, subscriptions. Read-only: creating, editing or cancelling a rule is the account holder's to do in the app. Use this to explain why an entry exists, or what is coming. ## Deliberately absent - No tool changes existing entry status or assigns a project. - No tool creates, edits, or cancels a recurring rule. A standing instruction keeps writing on its own, which is more than the one reviewable row an agent is trusted with. `list_recurring` exists so an agent can explain why an entry is in the ledger.