{"openapi":"3.1.1","info":{"title":"Proof Entry agent HTTP API","version":"1.0.0","description":"The authenticated bearer-token transaction API. All access is tenant-scoped. Agent writes default to pending proposals. Explicit confirm: true records validated structured data directly and includes it in totals. This specification does not describe the separate cookie-authenticated human write contract, authentication endpoints, receipt upload, or MCP JSON-RPC transport. Obtain an OAuth token through MCP setup or device-code authorization; do not substitute a browser session cookie."},"servers":[{"url":"https://staging.glidzr.com"}],"externalDocs":{"description":"HTTP API guide","url":"https://staging.glidzr.com/agents/http"},"security":[{"bearerAuth":[]}],"tags":[{"name":"Transactions","description":"Read entries, propose or explicitly record money in or out."}],"paths":{"/api/transactions":{"get":{"operationId":"listTransactions","tags":["Transactions"],"summary":"Read ledger entries","description":"Newest first. Defaults to confirmed entries and both directions. Invalid status values fall back to confirmed; unrecognized direction means both. Invalid dates are ignored. Reading first materializes due entries from existing human-authored recurring rules. Pending and rejected entries never count in totals.","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["confirmed","pending","rejected"],"default":"confirmed"}},{"name":"direction","in":"query","schema":{"type":"string","enum":["expense","income"]}},{"name":"from","in":"query","description":"Inclusive lower timestamp bound. Accepts ISO timestamps or YYYY-MM-DD, parsed at UTC midnight.","schema":{"type":"string"}},{"name":"to","in":"query","description":"Inclusive upper timestamp bound. A YYYY-MM-DD value means UTC midnight, not the end of that day. Supply an ISO timestamp for a precise end time.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Optional integer from 1 to 200. Omission defaults to 50; invalid or out-of-range values return 400.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"Entries matching the requested filters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionList"}}}},"400":{"description":"Invalid limit; use an integer from 1 to 200.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","headers":{"WWW-Authenticate":{"schema":{"type":"string"},"description":"Bearer resource_metadata=\"https://staging.glidzr.com/.well-known/oauth-protected-resource\""}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request rate limit reached. An ingress 429 may precede authentication and includes Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request service temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"proposeTransaction","tags":["Transactions"],"summary":"Propose or explicitly record an entry","description":"Requires a JSON object, at most 64 KiB. A bearer token proposes by default. Pass confirm: true with complete structured data to create a confirmed entry. No project assignment or standing instruction is available. There is no idempotency key: retrying a successful POST can create another entry.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/TransactionProposal"},{"$ref":"#/components/schemas/ConfirmedTransactionInput"}]},"example":{"description":"Train ticket","amount":"45.00","currency":"AED","direction":"expense"}}}},"responses":{"201":{"description":"Pending proposal, or confirmed entry when confirm: true was explicitly supplied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProposalResult"}}}},"400":{"description":"Invalid JSON, field value or domain input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","headers":{"WWW-Authenticate":{"schema":{"type":"string"},"description":"Bearer resource_metadata=\"https://staging.glidzr.com/.well-known/oauth-protected-resource\""}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds 64 KiB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request rate limit reached. An ingress 429 may precede authentication and includes Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request service temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"OAuth bearer token. Discover authorization at https://staging.glidzr.com/.well-known/oauth-authorization-server and follow https://staging.glidzr.com/agents/mcp or https://staging.glidzr.com/agents/device. Tokens are not assumed to be JWTs."}},"schemas":{"TransactionProposal":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"direction":{"anyOf":[{"type":"string","enum":["expense","income"]},{"type":"null"}]},"description":{"type":"string","minLength":1,"maxLength":200},"amount":{"type":"string","minLength":1},"currency":{"type":"string","minLength":3,"maxLength":3},"occurredAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"merchantName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"categorySlug":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"taxAmount":{"anyOf":[{"type":"string"},{"type":"null"}]},"taxRate":{"anyOf":[{"type":"string"},{"type":"null"}]},"supplierTaxId":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"reference":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"isBillable":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"clientName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]},"lineItems":{"anyOf":[{"maxItems":50,"type":"array","items":{"type":"object","properties":{"description":{"type":"string","minLength":1,"maxLength":200},"quantity":{"anyOf":[{"type":"number"},{"type":"null"}]},"unitAmount":{"anyOf":[{"type":"string"},{"type":"null"}]},"totalAmount":{"type":"string","minLength":1}},"required":["description","totalAmount"]}},{"type":"null"}]},"confirm":{"type":"boolean","const":false}},"required":["description","amount","currency"],"description":"Pending proposal input. Amount and printed tax are positive major-unit strings. Direction defaults to expense, date to today. Unknown fields are ignored. confirm must be false or omitted. Domain validation may return 400."},"ConfirmedTransactionInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"direction":{"anyOf":[{"type":"string","enum":["expense","income"]},{"type":"null"}]},"description":{"type":"string","minLength":1,"maxLength":200},"amount":{"type":"string","maxLength":64,"pattern":"^\\d+(?:\\.\\d+)?$"},"currency":{"type":"string","pattern":"^[a-zA-Z]{3}$"},"occurredAt":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"merchantName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"categorySlug":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"taxAmount":{"anyOf":[{"type":"string","maxLength":64,"pattern":"^\\d+(?:\\.\\d+)?$"},{"type":"null"}]},"taxRate":{"anyOf":[{"type":"string","maxLength":64,"pattern":"^\\d+(?:\\.\\d+)?$"},{"type":"null"}]},"supplierTaxId":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"reference":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"isBillable":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"clientName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]},"lineItems":{"anyOf":[{"maxItems":50,"type":"array","items":{"type":"object","properties":{"description":{"type":"string","minLength":1,"maxLength":200},"quantity":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"unitAmount":{"anyOf":[{"type":"string","maxLength":64,"pattern":"^\\d+(?:\\.\\d+)?$"},{"type":"null"}]},"totalAmount":{"type":"string","maxLength":64,"pattern":"^\\d+(?:\\.\\d+)?$"}},"required":["description","totalAmount"],"additionalProperties":false}},{"type":"null"}]},"confirm":{"type":"boolean","const":true},"fxRate":{"type":"string","maxLength":64,"pattern":"^\\d+(?:\\.\\d+)?$"}},"required":["description","amount","currency","occurredAt","confirm"],"additionalProperties":false,"description":"Explicitly confirmed structured entry. Requires confirm: true and a real yyyy-mm-dd date. Money/rates use decimal strings without grouping or currency symbols. Supply fxRate when currency differs from the ledger base currency. Invalid money, tax, references or conversion return 400 without creating an entry. No project assignment. Unknown fields are rejected. Never invent an amount or exchange rate."},"Money":{"type":"object","required":["minorUnits","currency","exponent","formatted"],"properties":{"minorUnits":{"type":"integer","description":"Integer minor units; use the supplied exponent, never assume /100."},"currency":{"type":"string","minLength":3,"maxLength":3},"exponent":{"type":"integer","minimum":0},"formatted":{"type":"string"}},"examples":[{"minorUnits":4500,"currency":"AED","exponent":2,"formatted":"AED 45.00"},{"minorUnits":4500,"currency":"JPY","exponent":0,"formatted":"JPY 4,500"},{"minorUnits":4500,"currency":"KWD","exponent":3,"formatted":"KWD 4.500"}]},"Transaction":{"type":"object","required":["id","direction","date","description","counterparty","category","client","project","amount","baseAmount","tax","deductible","billable","billed","status","source","recurringRuleId"],"properties":{"id":{"type":"string"},"direction":{"type":"string","enum":["expense","income"]},"date":{"type":"string","format":"date"},"description":{"type":"string"},"counterparty":{"type":["string","null"]},"category":{"type":["string","null"]},"client":{"type":["string","null"]},"project":{"type":["string","null"]},"amount":{"$ref":"#/components/schemas/Money"},"baseAmount":{"$ref":"#/components/schemas/Money"},"tax":{"anyOf":[{"$ref":"#/components/schemas/Money"},{"type":"null"}]},"deductible":{"type":["boolean","null"]},"billable":{"type":["boolean","null"]},"billed":{"type":["boolean","null"]},"status":{"type":"string","enum":["confirmed","pending","rejected"]},"source":{"type":"string"},"recurringRuleId":{"type":["string","null"]}}},"TransactionList":{"type":"object","required":["ok","status","direction","count","transactions"],"properties":{"ok":{"const":true},"status":{"type":"string","enum":["confirmed","pending","rejected"]},"direction":{"type":"string","enum":["expense","income","all"]},"count":{"type":"integer","minimum":0},"transactions":{"type":"array","items":{"$ref":"#/components/schemas/Transaction"}},"note":{"type":"string"}}},"ProposalResult":{"type":"object","required":["ok","transactionId","direction","status","message"],"properties":{"ok":{"const":true},"transactionId":{"type":"string"},"direction":{"type":"string","enum":["expense","income"]},"status":{"type":"string","enum":["pending","confirmed"]},"message":{"type":"string"}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"ok":{"const":false},"field":{"type":"string"}}}}}}