{"openapi":"3.0.3","info":{"title":"AgentBooks API","version":"1.0.0","description":"Autonomous double-entry ledger API for AI agents. Accepts payments from Stripe, L402, and Lightning Network — categorizes them with AI — and posts balanced journal entries automatically.","contact":{"email":"support@agentbooks.polsia.app"}},"servers":[{"url":"http://localhost:3000","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"Pass your API key as a Bearer token. Get one from POST /api/register."}},"schemas":{"Organization":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","example":"Acme Corp"},"slug":{"type":"string","example":"acme-corp-lz4k"},"created_at":{"type":"string","format":"date-time"}}},"Transaction":{"type":"object","properties":{"id":{"type":"integer"},"organization_id":{"type":"integer"},"amount":{"type":"number","example":49.99},"currency":{"type":"string","example":"USD"},"description":{"type":"string","example":"Pro plan subscription"},"source":{"type":"string","enum":["stripe","l402","lightning","manual"]},"external_id":{"type":"string","example":"pi_3OsJK2..."},"status":{"type":"string","enum":["pending","categorized","posted"]},"category":{"type":"string","example":"revenue"},"category_confidence":{"type":"number","example":0.97},"journal_entry_id":{"type":"integer","nullable":true},"occurred_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"TrialBalance":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","example":"1000"},"name":{"type":"string","example":"Cash"},"account_type":{"type":"string","example":"asset"},"total_debits":{"type":"number","example":1250},"total_credits":{"type":"number","example":0},"balance":{"type":"number","example":1250}}}},"totals":{"type":"object","properties":{"total_debits":{"type":"number"},"total_credits":{"type":"number"},"balanced":{"type":"boolean"}}}}},"Error":{"type":"object","properties":{"error":{"type":"string","example":"amount is required"}}}}},"tags":[{"name":"Auth","description":"Register and manage API keys"},{"name":"Transactions","description":"Record, categorize, and post payment events"},{"name":"Feeds","description":"Ingest webhooks from payment rails"},{"name":"Ledger","description":"Double-entry journal and trial balance"},{"name":"Accounts","description":"Chart of accounts management"}],"paths":{"/api/register":{"post":{"tags":["Auth"],"summary":"Register an organization","description":"Creates a new organization and returns an API key. No authentication required. **Save the API key — it cannot be retrieved again.**","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Acme AI Corp"}}}}}},"responses":{"201":{"description":"Organization created","content":{"application/json":{"schema":{"type":"object","properties":{"organization":{"$ref":"#/components/schemas/Organization"},"api_key":{"type":"string","example":"ab_live_xxxxxxxxxxxxx"},"note":{"type":"string"}}}}}},"400":{"description":"name is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Slug already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/org":{"get":{"tags":["Auth"],"summary":"Get organization info","description":"Returns current org details and list of API keys.","responses":{"200":{"description":"Org info","content":{"application/json":{"schema":{"type":"object","properties":{"organization":{"$ref":"#/components/schemas/Organization"},"api_keys":{"type":"array","items":{"type":"object"}}}}}}}}}},"/api/transactions":{"get":{"tags":["Transactions"],"summary":"List transactions","description":"Returns paginated transactions for the authenticated organization.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","categorized","posted"]}},{"name":"source","in":"query","schema":{"type":"string","enum":["stripe","l402","lightning","manual"]}}],"responses":{"200":{"description":"Transaction list","content":{"application/json":{"schema":{"type":"object","properties":{"transactions":{"type":"array","items":{"$ref":"#/components/schemas/Transaction"}},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}}}}},"post":{"tags":["Transactions"],"summary":"Record a transaction","description":"Manually record a payment event. The transaction starts in `pending` status — call `/categorize` then `/post` to complete the accounting cycle, or use `POST /api/reconciliation/run` to auto-process everything.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number","description":"Transaction amount (negative for expenses)","example":49.99},"currency":{"type":"string","default":"USD","example":"USD"},"description":{"type":"string","example":"Pro plan — January 2026"},"source":{"type":"string","enum":["stripe","l402","lightning","manual"],"default":"manual"},"external_id":{"type":"string","description":"Idempotency key — prevents duplicate transactions","example":"pi_3OsJK2..."},"occurred_at":{"type":"string","format":"date-time","description":"Defaults to now"},"metadata":{"type":"object","description":"Any additional key-value data"}}},"example":{"amount":49.99,"currency":"USD","description":"Pro plan subscription","source":"stripe","external_id":"pi_3OsJK2abc123"}}}},"responses":{"201":{"description":"Transaction created","content":{"application/json":{"schema":{"type":"object","properties":{"transaction":{"$ref":"#/components/schemas/Transaction"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Duplicate external_id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/transactions/{id}":{"get":{"tags":["Transactions"],"summary":"Get a transaction","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Transaction detail","content":{"application/json":{"schema":{"type":"object","properties":{"transaction":{"$ref":"#/components/schemas/Transaction"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/transactions/{id}/categorize":{"post":{"tags":["Transactions"],"summary":"AI-categorize a transaction","description":"Uses Claude to determine the category, confidence score, and recommended debit/credit accounts based on the transaction data and your chart of accounts.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Categorization result","content":{"application/json":{"schema":{"type":"object","properties":{"transaction":{"$ref":"#/components/schemas/Transaction"},"categorization":{"type":"object","properties":{"category":{"type":"string","example":"revenue"},"confidence":{"type":"number","example":0.97},"debit_account_code":{"type":"string","example":"1000"},"credit_account_code":{"type":"string","example":"4100"},"reasoning":{"type":"string"}}}}}}}}}}},"/api/transactions/{id}/post":{"post":{"tags":["Transactions"],"summary":"Post transaction to ledger","description":"Creates a balanced double-entry journal entry (debit + credit). Uses AI categorization accounts if available, falls back to Cash (1000) + Revenue (4000).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"debit_account_id":{"type":"integer","description":"Override debit account"},"credit_account_id":{"type":"integer","description":"Override credit account"}}}}}},"responses":{"200":{"description":"Journal entry created","content":{"application/json":{"schema":{"type":"object"}}}},"409":{"description":"Already posted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/feeds/stripe":{"post":{"tags":["Feeds"],"summary":"Stripe webhook ingestion","description":"Point your Stripe webhook at this endpoint with `?org_id=YOUR_ORG_ID` (or include `org_id` in your Stripe payment metadata for automatic routing). Verifies Stripe signature when `STRIPE_WEBHOOK_SECRET` env var is set — requests without a valid signature are rejected with 400. Handles `payment_intent.succeeded`, `charge.succeeded`, and `invoice.paid` events. No auth required.","security":[],"parameters":[{"name":"org_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Your organization ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Raw Stripe webhook event object"},"example":{"id":"evt_3OsJK2...","type":"payment_intent.succeeded","data":{"object":{"id":"pi_3OsJK2...","amount":4999,"currency":"usd"}}}}}},"responses":{"200":{"description":"Event received","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean"},"event_id":{"type":"integer"}}}}}},"400":{"description":"org_id missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/feeds/l402":{"post":{"tags":["Feeds"],"summary":"L402 payment ingestion","description":"Ingest HTTP 402 Protocol payment events.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["org_id"],"properties":{"org_id":{"type":"integer"},"payment_hash":{"type":"string"},"amount":{"type":"number"},"currency":{"type":"string","default":"BTC"},"preimage":{"type":"string"},"macaroon":{"type":"string"},"description":{"type":"string"}}}}}},"responses":{"200":{"description":"Event received","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean"},"event_id":{"type":"integer"}}}}}}}}},"/api/feeds/lightning":{"post":{"tags":["Feeds"],"summary":"Lightning Network settlement","description":"Ingest Lightning Network settlement events.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["org_id"],"properties":{"org_id":{"type":"integer"},"payment_hash":{"type":"string"},"amount_sat":{"type":"integer","description":"Amount in satoshis"},"amount_msat":{"type":"integer","description":"Amount in millisatoshis"},"settled":{"type":"boolean"},"memo":{"type":"string"}}}}}},"responses":{"200":{"description":"Event received","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean"},"event_id":{"type":"integer"}}}}}}}}},"/api/reconciliation/run":{"post":{"tags":["Ledger"],"summary":"Auto-reconcile","description":"Runs the full reconciliation pipeline: processes unprocessed feed events → categorizes pending transactions with AI → posts categorized transactions to the ledger.","responses":{"200":{"description":"Reconciliation complete","content":{"application/json":{"schema":{"type":"object","properties":{"events_processed":{"type":"integer"},"transactions_categorized":{"type":"integer"},"transactions_posted":{"type":"integer"},"errors":{"type":"array","items":{"type":"string"}}}}}}}}}},"/api/reconciliation/trial-balance":{"get":{"tags":["Ledger"],"summary":"Trial balance","description":"Returns a full trial balance — debits, credits, and net balance per account.","responses":{"200":{"description":"Trial balance report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrialBalance"}}}}}}},"/api/reconciliation/status":{"get":{"tags":["Ledger"],"summary":"Ledger status","description":"Returns whether the ledger is balanced, transaction counts by status, and count of unprocessed feed events.","responses":{"200":{"description":"Status report","content":{"application/json":{"schema":{"type":"object","properties":{"balanced":{"type":"boolean"},"transaction_status":{"type":"object"},"unprocessed_events":{"type":"integer"},"needs_attention":{"type":"boolean"}}}}}}}}},"/api/accounts":{"get":{"tags":["Accounts"],"summary":"List accounts","description":"Returns chart of accounts with computed debit/credit balances.","responses":{"200":{"description":"Account list","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"code":{"type":"string","example":"1000"},"name":{"type":"string","example":"Cash"},"account_type":{"type":"string","enum":["asset","liability","equity","revenue","expense"]},"total_debits":{"type":"number"},"total_credits":{"type":"number"},"balance":{"type":"number"}}}}}}}}}}},"post":{"tags":["Accounts"],"summary":"Create an account","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["code","name","account_type"],"properties":{"code":{"type":"string","example":"6000"},"name":{"type":"string","example":"Cloud Infrastructure"},"account_type":{"type":"string","enum":["asset","liability","equity","revenue","expense"]},"description":{"type":"string"}}}}}},"responses":{"201":{"description":"Account created","content":{"application/json":{"schema":{"type":"object"}}}}}}}}}