# VantedgeAI FundOS — Full API & Integration Reference for AI Agents # Last updated: 2026-06-22 (added LP Intent Radar + Portfolio & Pipeline News Feed) > FundOS by VantedgeAI — https://fundos.vantedgeai.com > Machine-readable integration guide for AI agents, LLMs, and developers. --- ## Authentication All API and MCP calls use Bearer token auth. Defensive note: the server's `_authenticate()` strips an accidental inner `Bearer ` prefix from the token before checking it (so requests with `Authorization: Bearer Bearer vdr_xxx` from agents that double- prefixed the env var still succeed). The CLI does the same client-side in `cli/fundos_cli/config.py::_clean_api_key()`. If you see a 401, the diagnostic block shipped with the CLI prints the redacted key prefix + base URL so you can spot env-mismatch errors in 3 seconds. ### API Key (recommended for AI agents) Generate in Settings → API Keys. Format: starts with `vdr_`. ``` Authorization: Bearer vdr_xxxxxxxxxxxxxxxx ``` ### JWT Token (24-hour, browser sessions) ``` POST https://fundos.vantedgeai.com/api/v1/auth/login {"email": "...", "password": "..."} → {"token": "eyJ...", "expires_in": 86400} ``` Rate limit: 100 req/min. Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. --- ## MCP Server (Claude, Cursor, other MCP clients) ```bash claude mcp add fundos https://fundos.vantedgeai.com/mcp ``` For SSE-only clients: https://fundos.vantedgeai.com/mcp/sse POST messages to the session URL returned in the SSE endpoint event. ### MCP Endpoints - POST /mcp Streamable HTTP — JSON-RPC 2.0 (recommended; the Streamable HTTP endpoint is https://fundos.vantedgeai.com/mcp) - GET /mcp/sse SSE stream (the SSE endpoint is https://fundos.vantedgeai.com/mcp/sse) - POST /mcp/message JSON-RPC 2.0 - GET /mcp/info Server capabilities - GET /mcp/tools Full tool list with JSON Schema - POST /mcp/call Simple REST tool call (no SSE needed) ### Available MCP Tools Tools marked * = require human approval before execution (side-effect tools). **Agent Context — call this FIRST** - fundos_get_agent_context Call this FIRST at the start of any multi-step workflow. Returns structured session briefing: recent tool calls, pending human-approval actions, active deals, LP roster changes, open risk alerts, upcoming capital calls, recently uploaded documents, and prior agent runs. Supports lookback_days (default 30, max 90). Read-only, costs 2 credits. **VDR / Deal Rooms** - list_deal_rooms List all deal rooms in the org (use to pick a room to inspect) - get_deal_room Load members + stats for a known room_id - create_deal_room* Spin up a new data room for diligence or LP onboarding (HUMAN APPROVAL) - list_documents Inventory documents in a room before searching or summarising - get_document_metadata Inspect a single document's metadata before downloading - get_document_download_url Fetch the raw download URL for a document file (PDF/XLSX/DOCX) - search_documents Answer free-form questions over a room with citations (RAG search) - fetch Read ONE document's full extracted text (id from search) — {id,title,text,url,metadata} - fetch_many Read the FULL TEXT of up to 50 documents in one call — use this when writing a memo or summary grounded in many documents - list_room_members Audit who has access to a room before granting more - add_room_member* Onboard a collaborator or LP to a room (HUMAN APPROVAL — expanding access) - list_users Match a person by email or build a team-wide report - get_audit_log Investigate suspicious access or build a compliance report - get_document_activity Per-document engagement signals — who actually read it and when - get_signature_status Check DocuSign envelope closing signature status across envelopes - list_qa_questions List diligence Q&A questions in a room (triage the Q&A queue) - answer_qa_question* Post a reviewed answer to an LP-visible Q&A question (HUMAN APPROVAL) **Deal CRM + Transactions + Pricer** - fundos_list_deals Read the full deal pipeline - fundos_get_deal Load full detail on one deal before drafting - fundos_create_deal* Add a qualified pitch or term sheet to the pipeline (HUMAN APPROVAL) - fundos_get_pipeline Render kanban view or compute per-stage deal counts - fundos_list_transactions Report on the closing pipeline or chase condition precedents - fundos_draft_transaction* Start a transaction record with default task pack (HUMAN APPROVAL) - fundos_run_pricer Score an asset: IRR, MOIC, WAL, cashflows, waterfall splits **Risk** - fundos_list_covenants Enumerate all monitored covenants (use to build risk dashboard) - fundos_check_covenant Test a covenant value when fresh financials arrive; alerts on breach - fundos_list_risk_alerts Retrieve the list of open portfolio risk alerts (pass open=true) - To trigger the Risk Agent (Agent F) to scan the whole portfolio, POST to /fundos/risk/agent/scan (web endpoint — see the Agents table below); there is no MCP tool for the scan itself, only for reading its results. **ODD / Diligence / CIM** - fundos_generate_odd Draft ODD answers when an LP sends a DDQ - fundos_vdr_analyze Surface red flags + entity map from a document bundle - fundos_list_cim_reports List existing CIMs / teasers / one-pagers - fundos_list_cim_templates Discover available CIM templates before generating - fundos_generate_cim Draft a CIM from source documents for IC or LPs **Investor Portal (LP)** - fundos_list_lps Enumerate all LP investors for rollups or reporting - fundos_get_lp Load full LP detail: commitment, KYC status, capital-call ledger - fundos_get_lp_memory Relationship "living brief" + engagement + confirmed asks/commitments for an LP. Call before drafting LP outreach. Read-only; MNPI excluded. - fundos_search_lp_interactions Search one LP's memory — asks/commitments (semantic) + recent interactions (keyword). Read-only; MNPI excluded. - fundos_create_capital_call* Issue a capital call (HUMAN APPROVAL — this affects LP cash) NOTE: Never automatically send LP capital-call or distribution notices to LP inboxes. Always draft first; humans click send. Route drafts to /fundos/investors/. **CFO Center** - fundos_list_fund_accounts List all fund vehicles — pick one before computing P&L - fundos_compute_pnl Compute P&L + NAV over a date range. READ-ONLY when called with inline entries — does NOT write journal entries to the database. To persist entries, use cfo.post_journal_entry via the web UI (requires human approval). - fundos_compute_waterfall Compute LP/GP splits at exit (European waterfall model) **Fund Administration** (web UI at /fundos/fund-admin — the software spine of an AI-native administrator) - NAV engine: deterministic NAV = Σ(position × independent price) + cash − liabilities − accruals, per fund account as of a date; per-position source-linked line items; tolerance/validation gate (NAV-move, stale/missing/unpriced price, negative NAV) → exception queue - Independent pricing: a PricingSource registry (priority hierarchy + independence flag) + dated PriceQuote; equity quotes via Finnhub, everything else entered manually until vendor feeds (Bloomberg/ICE/Refinitiv) are contracted - Four-eyes sign-off: a maker submits, a DIFFERENT reviewer approves/releases (segregation of duties enforced); open critical exceptions block release; immutable sign-off trail - Reconciliation: tie the book to an independent custodian/PB statement (positions auto-pulled from the book; custodian side uploaded) → break/exception queue; an opt-in per-fund gate blocks NAV release until the book reconciles clean - LP capital accounts: per-(fund, LP, period) roll-forward (beginning + contributions − distributions + allocated P&L − real management + incentive fees = ending; honors HWM/hurdle + per-LP terms; clawback exposure) → per-LP PCAP statement (HTML + XLSX) - Trade→GL bridge: fills auto-post balanced journal entries (idempotent, flag-gated FUNDOS_GL_AUTOPOST) so the GL cash the NAV reads stays current without hand-entry; a distribution hook posts when a distribution is fund-scoped - Investor register (transfer agency): units per (fund, LP, share class) from subscriptions/redemptions/transfers; the LP↔fund link the GL bridge uses to post distributions + capital-call contributions to the right fund - Financial statements + audit tie-out: GAAP **or IFRS** investment-company statements (Statement of Assets & Liabilities, Operations, Changes in Partners' Capital, Schedule of Investments, Statement of Cash Flows, Financial Highlights — ASC 946 period ratios: expense ratio, net-investment-income ratio, incentive-fee ratio, total return — a **fair-value hierarchy** (ASC 820 / IFRS 13: Level 1/2/3), and **notes to the financial statements** (organization, accounting policies, fair value, fees & carry, commitments, related parties, subsequent events)) assembled from the released NAV + capital accounts + GL and tied out to the NAV; HTML print view + XLSX (one sheet per statement + FV hierarchy + notes), and bundled into the CFO audit pack. Toggle US GAAP / IFRS basis - Distributions (waterfall): split a fund cash distribution through the European waterfall (return of capital → preferred return → GP catch-up → carry split) and allocate each LP's share pro-rata; created as a draft, a human issues it (posts the GL: DR LP/GP capital, CR cash). Deterministic - Deal-by-deal (American) waterfall: track per-deal investments (cost / proceeds / FMV + per-LP participation) and compute carry on EACH realized deal (return of capital + preferred on the deal's cost, then GP carry on its gain), with fund-level CLAWBACK exposure = deal-by-deal carry taken minus the whole-fund European entitlement. Deterministic - Equalization (subsequent close): a deterministic what-if calculator — for a later-close LP, the catch-up contribution (its pro-rata share of capital already called) + the equalization premium (interest from the first close to admission), and the per-existing-LP rebate + premium share - Loans (credit-fund accounting): the fund's loan book — interest accrual (cash-pay or PIK, interest = outstanding × coupon × days/day-count), amortization schedules (bullet / amortizing / level debt service), loss provisioning (impairment %), and a portfolio rollup (outstanding, weighted-average coupon, annual interest income, impairment reserve, net carrying value); deterministic, XLSX export - Investor report (LP pack): one consolidated per-LP report bundling the LP's capital account (PCAP), performance (TVPI/DPI/RVPI/IRR), commitments (committed/called/uncalled), management fee (gross/discount/net), and allocated fund expenses for the period — assembled deterministically from the other Fund Admin sections; printable HTML + XLSX. Each section degrades gracefully when its input isn't populated yet - Equalization (subsequent close): catch-up + equalization premium for a later-close LP, with per-existing-LP rebate/premium; the premium accrues per call date (each called tranche from its own date — the precise ILPA treatment) when the fund has issued capital calls, else simple interest off the first close - Management fee: a transparent, deterministic management-fee engine — stepped rates (investment-period → post-investment step-downs a flat schedule can't express), the fee basis (committed / invested / NAV), and per-LP side-letter discounts; computes the period fee = basis × annual rate × (days/365), allocated per LP, net of discounts; XLSX export. Falls back to the fund's fee schedule when no steps are defined - Commitments & uncalled capital: per-LP + fund-level commitment status — committed vs called (issued capital calls) vs contributed (funded), the uncalled (still-callable dry powder) and outstanding (called-but-unpaid) balances, and recallable distribution capacity (recyclable = uncalled + recallable); % called, XLSX export. LPs scoped to the fund via the investor register - Fund-expense allocation: record fund-level operating expenses (audit / legal / admin / organizational / tax) and apportion them across LPs deterministically — pro-rata by committed capital or split equally; organizational expenses honor a cap (excess reclassified GP-borne) and a management-fee-offset credit is reported (transaction/monitoring/director fees the LPA rebates against the fee). Per-LP + per-category rollup, XLSX export - Performance (TVPI / DPI / RVPI / IRR): the standard PE/VC return suite, fund-level and per-LP — paid-in capital (paid capital calls), distributions, and residual value (the latest released NAV; per-LP share pro-rata by committed capital). DPI = distributions/paid-in, RVPI = NAV/paid-in, TVPI = (distributions+NAV)/paid-in, IRR = money-weighted XIRR over the dated cashflows + residual NAV. Deterministic, XLSX export - Regulatory reporting: assemble Form PF (private-fund adviser), AIFMD Annex IV, and FATCA/CRS data packs from the released NAV (gross/net assets, leverage) + the LP register (beneficial owners, commitments, jurisdictions, KYC); generated as a reviewable DRAFT (status draft → reviewed → filed), with XLSX export. E-file export generates a prepared regulator-format XML (with pre-submission validation) for the official portal — FundOS prepares, never transmits; the human submits and records the confirmation # - Onboard an existing fund: a guided wizard (/fundos/fund-admin/onboard) for funds that already have an incumbent administrator/accounting system/custodian — it derives a 6-step checklist from your data (Discover → Fund setup → Import history → Shadow NAV → Reconcile → Cut over), deep-links each step to the right tool, ticks each step ✓ as the underlying data exists, and gates a human-confirmed cut-over that turns on the reconciliation release gate. The adoption motion is overlay → parallel/shadow → cut over: stand up a FundOS NAV alongside your current admin, reconcile the two, then switch slice-by-slice instead of starting from a blank page - GL connectors (QuickBooks Online + Xero): read-only OAuth connectors behind the fund's gl_provider that pull the chart of accounts + journal entries from your accounting system and map them deterministically to GLAccount/GLJournalEntry/GLJournalLine (idempotent by external id), so the cash + liabilities the NAV engine reads come straight from your books with no hand-entry. Read scope only — FundOS never writes back to your accounting system; OAuth consent happens in your own browser and tokens are stored encrypted. Connect from the onboarding wizard's Fund-setup step (/fundos/fund-admin/gl/connect/), then Pull on demand - Cap-table import (Carta / AngelList / Sydecar): upload a cap-table export and AI-extract investors + commitments into an editable preview that pre-matches each row to an existing LP; confirm to create LPs + seed the investor register opening positions (tagged auto:captable), establishing the LP↔fund link the capital-account, commitment, and distribution math need. Joins the prior-NAV, fund-expense, and loan-statement upload-and-extract imports (all draft-first, human-confirmed) - NOTE: NAV-path math is deterministic code (never an LLM) — a rerun produces the same NAV; nothing posts or releases without a human reviewer's sign-off **Syndication** - fundos_list_syndications List syndications and report raise progress - fundos_get_syndication Inspect a single syndication + allocation matrix - fundos_allocate* Record investor allocations (HUMAN APPROVAL) **HF Ops (DTCC ITP)** - hf_ops_dtcc_get_trade_status Investigate a settlement break by ctm_ref - hf_ops_dtcc_list_unaffirmed List confirms still pending T+0 affirmation - hf_ops_dtcc_get_affirmation_scorecard Report ops health to COO/PM - hf_ops_dtcc_lookup_ssi Fetch counterparty SSI when chasing a missing-SSI break **OMS / Trading** - oms_list_orders List orders (filter by status, fund account) - oms_get_order Order detail + execution timeline - oms_create_order* Submit a new order — pre-trade compliance runs automatically (HUMAN APPROVAL) - oms_list_positions Current position book - oms_check_pretrade Dry-run pre-trade compliance check (no order created) - oms_get_fix_status FIX engine sidecar health + per-session state **Model Portfolios + Rebalancing (Run 3)** - oms_models_list List all portfolio models for the org (read-only, 1 credit) - oms_models_get Load one model with weights + fund-account assignments (read-only, 1 credit) - oms_models_create* Create a new portfolio model with target weights (HUMAN APPROVAL, write) - oms_rebalance_propose* Generate a rebalance proposal (drift|manual|cash_flow) — detects band breaches, computes trade lines (HUMAN APPROVAL, 5 credits) - oms_rebalance_approve* Approve a proposal: creates OMS orders via pre-trade compliance (HUMAN APPROVAL, write) **Exception Inbox + Agent Resolution Playbooks** - exceptions_list List exceptions: filter by status/severity/module/type/age_days (read-only, 1 credit) - exceptions_get Full detail + event timeline for one exception (read-only, 1 credit) - exceptions_update Resolve/suppress/assign an exception — HUMAN APPROVAL REQUIRED (write, 2 credits) - playbooks_list List all agent resolution playbooks (org-specific + global defaults) (read-only, 1 credit) - playbooks_configure Create an org-specific playbook with step DSL — HUMAN APPROVAL REQUIRED (write, 2 credits) - exception_run_playbook Run the matching playbook on an exception — re-checks data, generates drafts; auto_resolve mode needs human approval (5 credits) **Compliance OS** - fundos_list_kyc_records List KYC/AML records - fundos_list_filings List regulatory filing deadlines - fundos_check_restricted_list Check if a ticker, ISIN, or company name is on the restricted list - fundos_list_obligations List the compliance obligations register Adviser tier (ERA): set the workspace adviser tier on the Adviser Profile page (/fundos/compliance/profile). Selecting Exempt Reporting Adviser seeds an ERA checklist (Form ADV Part 1A annual updating amendment at fiscal-year-end + 90 days, state notice filings, ERA-applicable obligations), enables a Form ADV draft generator, and turns on a deterministic AUM registration-trigger watcher that compares fund AUM (GP-entered regulatory AUM, else CFO Center NAV) against the $150M private fund adviser exemption ceiling. The watcher publishes a Fund Intelligence finding and shows on the GP + Compliance dashboards as it approaches/exceeds the threshold. This module drafts and reminds — it does not give legal advice; every regulatory specific is flagged "verify with counsel". **Utility / Discovery** - fundos_list_tools Discover the full FundOS tool catalogue - fundos_call_tool Invoke any tool by name with validated args - search Search adapter for ChatGPT Deep Research — returns {id, title, url}[] - fetch Read a VantedgeAI document's full text (paired with search) ### MCP Resources myvdr://rooms, myvdr://fundos/deals, myvdr://fundos/transactions, myvdr://fundos/covenants, myvdr://fundos/lps, myvdr://fundos/positions ### Dynamic Client Registration (RFC 7591) MCP clients self-register without a pre-configured client_id: ``` POST /oauth/register (no auth required) Content-Type: application/json { "client_name": "Codex CLI", "redirect_uris": ["http://localhost:54321/callback"], "grant_types": ["authorization_code"], "token_endpoint_auth_method": "none" } HTTP 201 { "client_id": "dyn_", "client_id_issued_at": , "grant_types": ["authorization_code"], "redirect_uris": [...], "token_endpoint_auth_method": "none" } ``` Discovery: `registration_endpoint` field in `/.well-known/oauth-authorization-server` and `/.well-known/mcp.json`. Rate limit: 10 registrations / IP / hour. Dynamic clients show `is_dynamic=True` in the DB; admins can revoke at `/admin/oauth/`. ### OAuth Scopes Always default to `read` scope for AI agents doing read-only work. - `read` — read-only access to all FundOS data (RECOMMENDED default for AI agents) - `write` — data entry; required for create/update operations - `admin` — organisation administration; NEVER request for read-only tasks Request `read` for workflows that only inspect data (list deals, read LP info, check covenants). Upgrade to `write` only when the workflow explicitly creates or modifies records (and human approval has been obtained). --- ## REST API Reference Base URL: https://fundos.vantedgeai.com/api/v1 Interactive docs: https://fundos.vantedgeai.com/api/docs ### VDR — Deal Rooms GET /rooms List rooms POST /rooms Create room GET /rooms/{id} Room detail + members GET /rooms/{id}/documents List documents POST /rooms/{id}/documents Upload (multipart) GET /rooms/{id}/documents/{doc_id}/download DELETE /rooms/{id}/documents/{doc_id} GET /rooms/{id}/members POST /rooms/{id}/members Invite {email, role} GET /rooms/{id}/qa Q&A questions POST /rooms/{id}/qa/{q_id}/answer GET /rooms/{id}/analytics/audit ### FundOS — Deal CRM GET /api/v1/fundos/crm/deals List deals POST /api/v1/fundos/crm/deals Create deal (?ephemeral=true to dry-run) GET /api/v1/fundos/crm/deals/{id} PATCH /api/v1/fundos/crm/deals/{id} GET /api/v1/fundos/crm/pipeline Deals grouped by stage CRM Copilot (web UI, on the Deal CRM + LP CRM index pages; cookie-auth JSON, same-origin): - POST /fundos/assist/query — {text, entity?}; Gemini turns a natural-language request ("deals stuck in diligence 30+ days", "family offices I haven't contacted in 21 days", "term sheets over $10M") into a constrained query spec executed against deals/LPs through a strict field whitelist (the model can only name mapped columns — no arbitrary attribute access), returning {entity, columns, rows, count, summary} for a click-through table. Falls back to a keyword heuristic when AI is unavailable. - GET /fundos/assist/activity — Unified agent activity timeline DERIVED from AgentRun + AgentAction (no parallel store). Powers the "what your agents did while you were away" feed with a new-since-last-visit badge. Returns {items, counts, server_now}. - POST /fundos/assist/import/parse — {text, entity}; paste a list/email/spreadsheet → AI-extracted deal/LP preview rows (no DB writes). - POST /fundos/assist/import/commit — {rows, entity}; create the reviewed rows (the human-approval gate; mirrors bulk import). Returns {created, ids}. ### FundOS — LP CRM GET /api/v1/fundos/lp-crm/investors POST /api/v1/fundos/lp-crm/investors/{id}/activity LP CRM Fundraising Pipeline (web UI, /fundos/lp-crm/...): - pipeline — 8-stage kanban (Identified→First Contact→Intro Meeting→Due Diligence→Soft Commit→Hard Commit→Closed/Won→Passed). Drag-and-drop cards; each move auto-logs a Stage Change signal. - analytics — Arc gauge (% of target raise committed), KPI cards, pipeline funnel (horizontal bars per stage), recent signals feed. - agent — AI outreach agent config: fund description, key differentiators, target LP profile, preferred tone, follow-up cadence. - POST //move-stage — JSON; moves LP to new stage; logs signal. - POST //log-signal — JSON; manually log a buying-intent signal (document_viewed, email_opened, meeting_attended, question_asked, referral, inbound_inquiry, follow_up_requested, no_reply, stage_change). - POST //draft-outreach — JSON {channel}; calls Gemini to draft email or LinkedIn message using agent config + LP signals; returns {ok, outreach_id, subject, body, suggested_cta}. - POST //outreach//status — JSON {status}; mark draft as sent or discarded. - POST //share-doc — JSON {document_name, share_link}; creates a trackable URL. - GET /track/ — Public (no login); increments view_count, logs document_viewed signal, redirects to original link. - POST //update-targeting — Form; saves target_commitment_usd, soft_commit_usd, hard_commit_usd, fit_score. Signal heat on LP cards: green = signal in last 7d, amber = 8–21d, grey = dormant. LP Intent Radar (/fundos/lp-crm/radar): every LP ranked by a composite buying-intent score (0-100 = 0.35·recency + 0.30·signal-momentum + 0.15·ICP-fit + 0.20·pipeline-stage) with human "why now" reasons drawn from owned, authenticated first-party engagement (data-room views via AuditLog, IR email opens/clicks, meetings) — no third-party ad de-anonymization, no general solicitation. Pure-Python scoring (no AI cost to rank). One-click intent-aware outreach Draft (review-only LPDevOutreach). The LP Autopilot (Agent A) scans in intent order and proposes high-intent outreach first. LP-portal data-room VIEW/DOWNLOADs auto-become document_viewed signals via a cron sweep (high-precision: only the LP's own portal user counts, never GP/staff views). ### FundOS — Portfolio & Pipeline News A cron-refreshed news feed for the companies in the deal book (active + pipeline deals; never passed/closed-lost or exited). Surfaced on the GP dashboard (1 latest headline per company + "N more") and a grouped feed page at /fundos/news/, newest first, link-out to source in a new tab. - Sources: Finnhub company-news for tickered/public names; Google News RSS (free, no key) for private companies, keyed by name. - Relevance: an LLM filter (one Gemini call per Google-News batch, thinkingBudget 0) keeps only headlines about THIS company using its context — "what it does" seeded from the Deal plus the company's own homepage description fetched from its domain — so a startup named "Sherpa" drops news about Nepal mountain guides. Best-effort (degrades to unfiltered if AI unavailable). Finnhub (symbol-keyed) skips the filter. - Per-org: Organization.news_feed_enabled (admin toggle at /fundos/news/settings); env NEWS_FEED_ENABLED is an optional global force-on. Ships dark (default off, every org). - /fundos/news/cron/refresh (Bearer CRON_SECRET) — new-only on the cron; the settings "Refresh now" dispatches a background deep job that also re-filters existing headlines. Read-only; nothing auto-sends. LP IR Communications (segmented distribution lists + email campaigns, /fundos/lp-crm/...): - segments — Distribution lists. Static (hand-picked LPs) or dynamic (saved filter over pipeline stage, entity type, priority, KYC status, committed capital, consultant flag — auto-updates). - segments/new, / (preview resolved members + sendable/no-email counts), //delete. - campaigns — IR campaign list with per-campaign sent/open/click rollups. - campaigns/new, / (compose + recipients + stats + send controls). - POST /campaigns//draft-ai — JSON {topic}; Gemini drafts subject+body grounded on the agent config + the fund's Answer Bank. - POST /campaigns//send-test — Send a one-off test to yourself before sending for real. - POST /campaigns//send — Human send gate: materializes recipients from the segment, drains the first batch; the rest deliver automatically. - POST /campaigns//send-batch — Drain one batch (client-driven continue loop). /pause, /delete. - GET /ir/settings (admin) — Per-org send provider: native SMTP, or SendGrid/Mailchimp with an encrypted API key + from/reply-to. - GET /ir/open/.gif — Public open pixel; logs an email_opened signal on the LP. - GET /ir/click/ — Public click redirect; logs a follow_up_requested signal, then 302s to the target. Nothing sends automatically — a human clicks Send on each campaign. Opens and clicks feed buying-intent signals back into the pipeline + analytics. LP Prospecting Connectors (seed the pipeline from external sources, /fundos/lp-crm/...): - sources — Connector list + recent import runs + review-queue count. - sources/new (admin) — Add an Apollo.io connector (API key stored encrypted) with a people-search config (org keyword, titles, locations); or a custom REST endpoint. - POST /sources//run — Synchronous pull → dedupe/upsert candidates → review queue. - import/csv — Upload or paste a CSV (Dakota Marketplace export, LinkedIn Sales Navigator export, or any CSV); columns auto-map (override per field). Rows land in the review queue. - sources/review — Triage imported prospects (needs_review=True). Accept → pipeline at Identified stage; Drop → delete. - POST /sources/cron/pull — Bearer CRON_SECRET; runs every enabled connector daily. Dakota's API is partner-gated and LinkedIn has no usable prospecting API — both flow through CSV export import. ### FundOS — Pricer POST /api/v1/fundos/pricer IRR/MOIC/WAL/waterfall — ?ephemeral=true safe ### FundOS — Risk GET /api/v1/fundos/risk/covenants POST /api/v1/fundos/risk/covenants/{id}/check GET /api/v1/fundos/risk/alerts ### FundOS — Credit Facilities + Borrowing Base GET /api/v1/fundos/risk/facilities Facilities with commitment/outstanding GET /api/v1/fundos/risk/facilities/{id} Terms + rules + rates + limits + latest run POST /api/v1/fundos/risk/facilities/{id}/bb/run Run borrowing base — body {"tape_id"?: N, "ephemeral": true} for a what-if that persists nothing (use before proposing a draw) GET /api/v1/fundos/risk/facilities/{id}/bb/{run} Run detail incl. per-loan eligibility verdicts Web: /fundos/risk/facilities (workspace), /fundos/risk/facilities/{id}/certificate (+.xlsx), /fundos/risk/facilities/{id}/lender-pack.zip Nightly computed-covenant scan (deterministic re-derivation — NOT the risk agent): GET /fundos/risk/cron/covenant-scan (Bearer CRON_SECRET, 23:00 UTC weekdays). To trigger the risk_agent (Agent F) portfolio scan that drafts lender notices, POST /fundos/risk/agent/scan. ### FundOS — Remittances, Stress Test, Treasury, Slack Q&A Web: /fundos/pricer/remittances (servicer collection reports → per-loan reconciliation vs the tape series; breaks → Exception Inbox) Web: /contracts/{doc_id}/stress-test (proposed term-sheet terms vs the live loan book; deterministic verdict + optional AI counter draft, display-only) Web: /fundos/treasury (facility outstanding + availability; read-only Plaid bank balances when PLAID_CLIENT_ID/SECRET are configured — ships dark, no payments ever) Slack two-way Q&A: mention the FundOS bot or DM it ("what's our exposure to consumer loans?") — org-scoped answers via the Copilot; configure at /admin/integrations/slack-qa (Slack v0 signature-verified receiver at POST /webhooks/slack/events; one Slack team maps to exactly one organization) Daily bank-balance refresh: GET /fundos/treasury/cron/refresh (Bearer CRON_SECRET; no-ops while Plaid is unconfigured) ### FundOS — Headless ingest + loan-ledger bridge + GL accrual POST /api/v1/fundos/pricer/tapes Push a loan tape (base64 body). Auto-commits ONLY when a human confirmed this source's column mapping once; first uploads land as drafts with a review URL POST /api/v1/fundos/pricer/remittances Push a servicer remittance — auto-commits + reconciles under the same trust rule; breaks land in the Exception Inbox Email-inbound ingest: servicers can EMAIL tapes/remittances (CSV/XLSX attachments) to the org's inbound address — admins allow-list each servicer's sending address at /fundos/pricer/ingest-routes (two factors must match: the org's secret inbound address AND the allow-listed sender); the same mapping trust rule applies (first file from a new source drafts; auto-commit only after a human confirmed the mapping once), and routed senders skip deal-pitch triage entirely Web: /fundos/pricer/tapes/{id}/sync-fa — preview→commit bridge from the tape book into Fund Admin's loan ledger (accruals/NAV; human-gated) Fund setting "Accrue loan interest to the GL daily" (default off): idempotent per-loan daily JEs — Dr receivable / Cr income, PIK capitalizes, defaulted loans are non-accrual MCP (hosted /mcp): fundos_list_deals, fundos_get_deal, fundos_get_pipeline, fundos_list_lps, fundos_get_lp, fundos_list_covenants, fundos_check_covenant (ephemeral or stored), fundos_list_risk_alerts, fundos_run_pricer, fundos_compute_pnl, fundos_compute_waterfall, fundos_list_fund_accounts, fundos_list_facilities, fundos_run_borrowing_base (EPHEMERAL by default — run the what-if before proposing a draw) ### FundOS — Investor Portal GET /api/v1/fundos/investors/lps GET /api/v1/fundos/investors/lps/{id} Includes capital-call ledger POST /api/v1/fundos/investors/lps/{id}/capital-calls ### FundOS — CFO Center GET /api/v1/fundos/cfo/accounts Fund account list POST /api/v1/fundos/cfo/report P&L + NAV computation POST /api/v1/fundos/cfo/waterfall European waterfall splits CFO Center v2 — Fund Performance + Period Close (web UI, /fundos/cfo/accounts//...): - dashboard — 6-tile live overview (MTD/QTD/YTD P&L, Risk Metrics, Top Movers, Period Close, LP Waterfall, Benchmark sparkline) - performance — MTD/QTD/YTD P&L tabs + Chart.js fund vs SPY/QQQ benchmark line chart - risk — Sharpe ratio (12-month), fund leverage (gross/net), bond portfolio DV01 - movers — Top 10 P&L contributors by position (DAILY/MTD/QTD/YTD) - period-close — Run month/quarter/year-end closes; locks P&L; runs LP waterfall (HF: on realized+unrealized; PE/VC/PC: on realized only) - period-close — GL LOCK (book-of-record control): while a period is closed, journal entries dated on/before its period end are rejected from every surface (manual JE, REST API, auto-posting, QBO/Xero sync); posted entries + lines are append-only — corrections are dated reversing entries in the open period - period-close//reopen — POST, workspace-admin only: audited reopen (reason required, kept on the trail) that unlocks GL posting for the period - accruals/true-up — POST: management-fee TRUE-UP — compares booked (crystallized accruals) vs the actual invoice for a period and drafts the adjusting JE (under-accrual books expense, over-accrual releases it; draft-first, never auto-posted; dated in the open period when the target period is locked) - capital-call receivable flow: issuing a call posts DR Capital Call Receivable / CR LP Partner Capital; the paid event relieves the receivable (DR Cash / CR Receivable) — NAV cash moves only when money lands; legacy calls without an issued entry keep DR Cash / CR Partner Capital - four-eyes beyond NAV: manual journal entries always save as DRAFTS (UI + REST API — is_posted in the body is ignored) and a DIFFERENT team member posts them (maker ≠ poster enforced); distribution issuance requires an issuer different from the drafter; fee-schedule changes are workspace-admin-only - external-auditor role (User.is_auditor, admin-assigned on /admin/users): a READ-ONLY scope — the account reaches only audit packs, the trial balance, and the GL journal (GETs); everything else 403s; every allowed view is written to the immutable audit log (AUDITOR_VIEW) so the fund can show exactly what its auditor saw and when; admin/superadmin flags override - ILPA quarterly report (G2): /fundos/fund-admin/lp-report -> "Generate ILPA report" (one LP) or "All LPs" (whole register) renders the quarterly report in the ILPA Reporting Template layout (capital account statement with fees gross->offsets->net, commitment schedule, since-inception performance incl. net XIRR) as XLSX and FILES it into the LP's document vault (category "Quarterly Report (ILPA)"); deterministic Layer-1 composition of PCAP + performance + commitments + fee + expense engines — never an LLM - LP portal Statements (G2): /portal/lp/statements now live — the LP sees their own published statements (ILPA quarterly reports, capital-account statements, K-1s, notices) with downloads, plus their capital-account roll-forward history; strictly scoped to the logged-in LP's own record and vault - K-1 tax data package (G3): /fundos/cfo//k1/package?tax_year=YYYY downloads the CPA workbook — every LP's DERIVED K-1 boxes (distribution character from typed distribution rows, Box 1 = the fund's posted GL income x the FUND-scoped register share, Box 13W = stored fee lines net of side-letter discounts), Item L GAAP capital + a mechanical tax-basis ending (GAAP minus the LP's share of unrealized P&L from period closes), fund totals that foot, 1099-INT data for credit funds, and an assumptions sheet ("FundOS assembles, your CPA reviews and files" — never tax advice); also fixes the single-K-1 generator to use the fund-scoped ownership share (was diluting across the whole org) - Multi-entity structures (G4): fund accounts link into structures via a parent pointer + relation_type (feeder | parallel | spv | blocker) with an ownership % — /fundos/cfo/accounts//master-feeder manages links (admin-only, cycle-guarded); intercompany P&L-allocation entries post per-entity account pairs (master DR 4900 P&L-allocated-to-feeders / CR 2850 due-to-feeders; feeder DR 1350 due-from-master / CR 4800 allocated income; loss flips legs; idempotent per period; GL period lock applies); CONSOLIDATED NAV is a reporting view over each entity's latest released NAV with intercompany eliminations (matched due-from/due-to pairs net out, unmatched investment-in-master assets stripped) and minority interest for partially-owned SPVs/blockers — never persisted as a NAV run; feeder LPs' reports carry a look-through line (LP share of feeder x feeder %% of master = effective master exposure) - Shadow NAV (G5a): a nightly cron (mon-fri 22:00 UTC, /fundos/fund-admin/cron/shadow-nav) computes an ADVISORY draft NAV per NAV-module fund with the same deterministic engine + validation checks as the official close (period_type=shadow, one per fund per day, 14-day retention); the NAV page shows a shadow strip (today's NAV, delta vs prior, anomaly badges, Refresh-now); shadow runs can NEVER be submitted or signed — month-end becomes review-and-sign ("T+1 NAV" vs a traditional administrator's T+10-15) - Auditor Q&A agent (G5b): POST /fundos/cfo/accounts//audit-qa — grounded, citation-only answers over the fund's audit surfaces (trial balance, capital accounts, fee schedule, released NAVs); answers strictly from that context with a section citation per figure, declines + names the artifact to request when the context lacks the answer; question text is fenced as untrusted input; read-only and available to the external-auditor role - Unmarked-portco guard + NAV staleness notice (G5c): an active portfolio company with NO mark is a named warning on the NAV run (it used to be silently valued at 0); the NAV page warns when portfolio valuation changes were recorded AFTER the last released NAV (the official number may be stale) - Add-investor doc filing (G5d): the new-LP form takes optional onboarding documents (subscription/KYC/side letter) filed straight into the investor's vault at creation - period-close/ — LP waterfall allocation detail; HF incentive fee shown as accrual - lp-terms — Per-LP hurdle/carry/preferred return overrides (blank = fund default) - chart-data — JSON endpoint for Chart.js benchmark chart data (SPY, QQQ, Fund NAV) CFO Center Audit Pack (web UI, /fundos/cfo): - Generate a ZIP audit pack (trial balance, LP capital roll-forward, mgmt fee, waterfall, cover memo) for any fund account with a custom as-of date. - View the contents of any generated pack (individual file list with per-file download buttons). - Delete any audit pack (including errored ones) via the trash icon. - Per-account persistent configuration via AuditPackConfig: toggle each of the 5 standard artifacts on/off and attach extra VDR documents to include in the pack. Config is shared across all CFO users in the workspace. - Downloads are proxied through Flask (authenticated); direct DO Spaces URLs are not exposed. OMS Multi-Asset Order Entry (June 2026): - New Order modal supports 8 instrument types: EQUITY, ETF, BOND, HY_BOND, PREFERRED, OPTION, FUTURE, SWAP - Selecting a type dynamically reveals type-specific fields (CUSIP/coupon/maturity/face_value/YTM for bonds; underlying/strike/expiry/option_type for options; contract_code/multiplier/tick_size for futures; swap_type/notional/fixed_rate/floating_index for swaps) - InstrumentSpec rows created alongside orders; position book shows DV01 + Duration columns for bond positions - Benchmark prices (SPY, QQQ) fetched nightly from Finnhub at 9pm UTC via cron /fundos/cfo/cron/benchmark-refresh OMS Tax Lot Tracking (June 2026): - Every buy creates a TaxLot row (FIFO — IRS default lot method) - Every sell matches against open lots oldest-first; realized G/L recorded per lot - Position book: click any position row to expand individual lots with ST/LT badge + unrealized G/L - Short-term: held < 365 days (ordinary income rates); long-term: held ≥ 365 days (preferential 0/15/20%) - Tax Summary page (/fundos/oms/tax-summary): annual realized ST/LT gains/losses + open lot unrealized exposure - Wash-sale detection: flagged when a repurchase occurs within 30 days of a loss close - All figures are informational; consult your tax advisor for 1099-B reconciliation and filing OMS Historical Lot Import (June 2026): - GET/POST /fundos/oms/lots/import — two-step upload (preview → confirm) for bulk CSV lot import - Accepts any broker or spreadsheet export; auto-maps column aliases (symbol→ticker, shares→quantity, price→cost_basis, date→acquired_date, fund→fund_account, ccy→currency, etc.) - Columns: required: ticker, acquired_date, quantity, cost_basis; optional: instrument_type, fund_account, currency - Date formats supported: YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, YYYY/MM/DD; BOM-stripped UTF-8 - Preview step groups lots by ticker+account, shows total shares and total cost; error rows listed separately and skipped - Commit step creates TaxLot rows (buy_order_id=None, currency=USD default or per-row) and WAC-merges into Position (no existing positions overwritten) - "Import Lots" button added to /fundos/oms/positions top-right action bar CFO Master-Feeder Fund Accounting — Gap #5 (June 2026): - FundAccount model: self-referential FK parent_fund_account_id (INTEGER REFERENCES fundos_fund_accounts(id)), allocation_pct (NUMERIC 8,4), feeder_funds dynamic relationship, is_master/is_feeder properties - GET /fundos/cfo/accounts//master-feeder — master fund card + feeder table + YTD consolidated P&L + link/unlink forms - POST /fundos/cfo/accounts//master-feeder/allocate — post intercompany GL entries for a period (YYYY-MM); idempotent by reference key mf_alloc::: - POST /fundos/cfo/accounts//master-feeder/link-feeder — designate an existing fund account as feeder + set allocation_pct; entity_type auto-set to "feeder" - POST /fundos/cfo/accounts//master-feeder/unlink-feeder/ — remove feeder relationship - app/services/master_feeder.py: get_structure(), compute_consolidated_pnl(), post_allocation_entries(), validate_allocations() - GL entries: master side DR 1300 Due-from-Feeder / CR 4900 Intercompany Allocation Income; feeder side DR 4800 Allocated Income from Master / CR 2900 Due to Master Fund - Allocation pcts need not sum to 100%; master absorbs residual (common in GP participation structures) - Migration: ALTER TABLE fundos_fund_accounts ADD COLUMN IF NOT EXISTS parent_fund_account_id + allocation_pct + index - New Account form updated with parent fund selector (auto-filters to non-feeder accounts); "Master-Feeder" link in CFO subnav HF Price Reconciliation — 3rd Recon Break Type (June 2026): - 5th file upload slot "PB prices" on /fundos/ops/recons/new — prime broker closing price CSV (columns: symbol, price/current_price/mark, currency, price_date; auto-mapped) - HFPriceRow model (hf_price_rows table): stores parsed PB price rows per recon run (source_type='pb'); recon engine derives internal prices from existing position rows (market_value / abs(quantity)) - _reconcile_prices() in app/services/hf_ops/recon.py: compares internal per-share price vs PB closing price per (canonical_symbol, currency); tolerances: 1% (PRICE_TOL_PCT) with $0.05 floor (PRICE_TOL_MIN); critical if deviation >= 3% (PRICE_CRIT_PCT) - break_type='price', classification='price_break' (both sides present, deviation exceeds threshold) or 'price_missing' (PB price exists but no internal position) - HFReconRun new columns: pb_prices_blob, price_total, price_matched, price_break_count; new price_match_pct property - recons_detail.html: price stat cards (matched/total + %) and price breaks count card shown only when price_total > 0; PB prices download link - Migration: hf_price_rows CREATE TABLE IF NOT EXISTS; ALTER TABLE hf_recon_runs ADD COLUMN IF NOT EXISTS (pb_prices_blob, price_total, price_matched, price_break_count) - Flash message on commit includes price break count when PB price file was uploaded CFO NAV Accruals — Daily Management Fee Engine (June 2026): - GET /fundos/cfo/accounts//accruals — daily management-fee accrual dashboard - POST /fundos/cfo/accounts//accruals/run — manually trigger today's accrual entry - POST /fundos/cfo/accounts//accruals/crystallize — crystallize a period (posts GL journal entry) - GET /fundos/cfo/cron/daily-accruals — cron: runs all fund accounts every weekday at 09:30 ET - NavAccrualEntry model (fundos_nav_accruals table): one row per (fund_account, date); stores nav_basis, rate_annual, days_divisor (252 HF / 365 other), accrual_amount, cumulative_mtd, period_label, status - Formula: daily_fee = nav_basis × (annual_rate / days_divisor); divisor = 252 for HF (trading-day), 365 for PE/VC/PC (calendar-day) - Status lifecycle: accrued → crystallized (GL entry posted) → reversed (manual adjustment) - Crystallization posts DR Management Fee Expense 5100 / CR Management Fee Payable 2100; GL entry linked from each row - YTD bar chart shows per-month accruals; green = crystallized, blue = open - Idempotent: re-running an accrual for an existing date is a no-op (skipped with info flash) - Migration: CREATE TABLE IF NOT EXISTS fundos_nav_accruals (...) OMS Multi-Currency FX Rates (June 2026): - GET /fundos/oms/fx-rates — daily FX rate dashboard; shows 1 foreign = X USD for all tracked currencies + 1 USD = X foreign inverse - GET /fundos/oms/cron/fx-refresh — Finnhub /forex/rates?base=USD fetch + upsert; runs weekdays 9PM UTC via Vercel cron - FXRate model (fundos_fx_rates table): from_currency, to_currency, rate (1 foreign = rate USD), trade_date, source; UNIQUE (from_currency, to_currency, trade_date) - app/services/fx_rates.py: fetch_and_store_rates(), get_rate(), convert_to_usd(), latest_rates() (DISTINCT ON from_currency for latest snapshot) - Finnhub rate inversion: Finnhub returns 1 USD = N foreign; we store 1/N so rate always means "1 foreign = X USD" - TaxLot.currency column (VARCHAR 3, default USD) allows per-lot currency tagging for multi-currency books - CCY badge displayed on positions table for non-USD holdings; USD positions show plain "USD" in grey - Migration: ALTER TABLE fundos_tax_lots ADD COLUMN IF NOT EXISTS currency VARCHAR(3) NOT NULL DEFAULT 'USD'; CREATE TABLE IF NOT EXISTS fundos_fx_rates (...) AI FDE — Fund Onboarding Automation (June 2026): The AI FDE automates fund client onboarding end-to-end. An admin creates an onboarding at /fundos/fde/, which generates a shareable link (/onboard/). The fund's COO/CFO chooses between two discovery paths: DISCOVERY PATH A — Document upload (recommended): 1. Client uploads PPM, pitch deck, or any combination of up to 3 PDFs (≤5 MB each). 2. POST /onboard//upload (multipart/form-data, field name "docs") → Gemini multimodal extracts Fund Profile from the documents → Sets discovery_mode="doc_upload" on the FundOnboarding record → Seeds a gap-fill opening message confirming what was extracted → Returns {success, profile, extraction_summary, opening_message} 3. A short 4–6 question follow-up fills in gaps the documents didn't cover (tech stack, pain points, priorities, integration constraints). 4. When follow-up is complete, discovery_complete=true. DISCOVERY PATH B — Q&A interview (fallback): Clients who don't want to share documents or don't have them yet complete a ~30-question async conversation. The opening screen shows 6 fund-type pill buttons; each subsequent turn shows [OPTIONS: A | B | C] pills for finite- answer questions. All state persists so clients can close and return later. Both paths produce the same structured Fund Profile JSON. When complete, the admin clicks Configure to set up the FundAccount, pipeline stages, and LP placeholder. DISCOVERY SCOPE (both paths): fund type (hedge_fund/vc_fund/pe_fund/private_credit/ family_office), AUM, investment strategy, team size, domicile, GP location, launch timeline, regulatory status (SEC/CFTC/AIFMD/FCA), existing systems (prime broker, fund admin, compliance system, PM system, data provider), trading instruments, reporting requirements, pain points, priority deliverables, integration requirements. MODULE SELECTOR RULES: - cfo_center: always enabled - gp_admin_dashboard: always enabled - lp_portal: hedge_fund / pe_fund / vc_fund / private_credit - oms: any trading instruments present - trading_fix_engine: equities / fixed_income / options / futures / fx in instruments - compliance_os: SEC or CFTC registered - deal_room: vc_fund or pe_fund - lp_crm: pe_fund / vc_fund / private_credit Admin routes (login required): GET/POST /fundos/fde/, GET /fundos/fde/runs/, POST /fundos/fde/runs//configure Public routes (token auth): GET /onboard/, POST /onboard//message, POST /onboard//upload, GET /onboard//status The /onboard//message response shape: {reply, choices, status, question_count, discovery_complete} `choices` is a string[] of clickable options stripped from Gemini's [OPTIONS: A|B|C] block. An empty array means the question is free-text. The /onboard//upload response shape: {success: true, profile: {...}, extraction_summary: "...", opening_message: "..."} On failure: {error: "extraction_failed", message: "..."} — client falls back to Q&A path. DB columns on fund_onboardings: discovery_mode ("qa" | "doc_upload"), doc_extraction_json (raw extracted profile + summary + file_count stored as JSON). Model: gemini-2.5-pro by default (override via GEMINI_FDE_MODEL env var without redeploy). Chat turns use thinkingBudget=0; profile extraction uses thinkingBudget=2048. Document extraction uses Gemini multimodal with inline_data base64 PDF parts. Database tables: fund_onboardings, fund_discovery_sessions, fund_impl_documents, fund_impl_tasks, fund_change_requests All discovery turns are billed via gemini_call(feature=fundos.fde.discovery) and linked to AgentRun for observability. Phases 2-5 (planning docs, config orchestration, UAT, change requests) are planned for future builds. ### FundOS — OMS / Trading GET /api/v1/fundos/oms/orders List orders (status, fa_id filters) POST /api/v1/fundos/oms/orders Submit order (runs pre-trade compliance) GET /api/v1/fundos/oms/orders/{id} Order + executions GET /api/v1/fundos/oms/positions Position book POST /api/v1/fundos/oms/pretrade Dry-run compliance check (no order created) GET /api/v1/fundos/oms/fix-status FIX sidecar health + session state ### FundOS — Model Portfolios + Rebalancing GET /api/v1/fundos/oms/models List portfolio models GET /api/v1/fundos/oms/models/{id} Model detail + weights + assignments POST /api/v1/fundos/oms/models Create model with weights GET /api/v1/fundos/oms/rebalance List rebalance proposals POST /api/v1/fundos/oms/rebalance/propose Generate proposal (drift|manual|cash_flow) POST /api/v1/fundos/oms/rebalance/{id}/approve Approve proposal → creates OMS orders Web UI routes (module flag: rebalancing): GET /fundos/oms/models Portfolio models grid GET /fundos/oms/models/new Create model form GET /fundos/oms/models/{id} Model detail (weights, drift table, assignments) GET /fundos/oms/models/{id}/edit Edit model settings POST /fundos/oms/models/{id}/weights Add a weight row POST /fundos/oms/models/{id}/weights/{w}/delete Delete a weight row POST /fundos/oms/models/{id}/assign Assign model to fund account POST /fundos/oms/models/{id}/unassign/{a} Unassign GET /fundos/oms/proposals Proposals list (filter by status) POST /fundos/oms/proposals/generate Generate proposal (form submit) GET /fundos/oms/proposals/{id} Proposal detail + trade lines POST /fundos/oms/proposals/{id}/approve Approve → OMS orders POST /fundos/oms/proposals/{id}/cancel Cancel ### FundOS — Syndication GET /api/v1/fundos/syndication POST /api/v1/fundos/syndication/{id}/allocate ### Stateless Document API — no FundOS account required Developers, law firms, fund admins, and LPs can call these endpoints with only a `doc_` API key. All data is supplied inline. No fund account, no pre-loaded data. Outcome-based billing — charged per successful document at rates set in the caller's enterprise agreement (contact https://fundos.vantedgeai.com/contact for access). POST /api/v1/documents/k1 — Schedule K-1 Form 1065 (per partner) POST /api/v1/documents/odd — ODD/DDQ completion POST /api/v1/documents/analyze — Document red-flag + entity-map POST /api/v1/documents/waterfall — European waterfall POST /api/v1/documents/pricer — IRR/MOIC/WAL pricer Auth for all: `Authorization: Bearer doc_` K-1 minimal body: { "fund_name": "Eight Capital Fund II", # required "tax_year": 2025, # required "partner_name": "Aksia LP", # required "lp_share_pct": 0.15, # optional "capital_account_start": 1000000, # optional "contributions_year": 0, # optional "box_1_ordinary_income": 45000, # income boxes (all optional, default 0) "box_9a_lt_gain": 105000, "box_13_deductions": 2500, "distributions": 0, # OR dist_roc/dist_income/dist_lt/dist_st/dist_recallable "format": "html" # only format supported today } Returns: { "html": "...", "filename": "k1_2025_aksia_lp.html", "charged_usd": 5.00, "charge_reason": "charged" } ODD minimal body: { "fund_info": {"fund_name": "...", "strategy": "VC pre-seed", "aum": 20000000}, "questions": ["Describe your investment process.", "..."] } Returns: { "answers": {...}, "charged_usd": 25.00, "token_usage": {...} } Analyze body: { "documents": [{"name": "cim.pdf", "text": "...full text..."}, ...] } Returns: { "summary": "...", "red_flags": [...], "entity_map": {...}, "charged_usd": 3.00 } Waterfall body: { "distributable": 1000000, "committed": 1000000, "hurdle_pct": 8, "carry_pct": 20 } Returns: { "lp_total": 916000, "gp_total": 84000, "tiers": [...], "charged_usd": 0 } All endpoints: accept `vdr_` OR `doc_` keys; trial_active orgs pay $0 for all. Developer orgs (plan=developer): no seat fee; outcome charges only. Developer dashboard: https://fundos.vantedgeai.com/developers/dashboard — key table + monthly usage. --- ## Triggering AI Agents FundOS has 9 AI agents (A–I). They are triggered via POST, stream events via SSE, and propose AgentAction rows that humans approve before execution (the CFO Flux agent is read-only commentary and proposes nothing). | Agent | What it does | Trigger endpoint | |-------|-------------|-----------------| | A — LP Fundraising Autopilot | LP follow-up emails, meeting prep | POST /fundos/lp-crm/ → "Run Autopilot" button | | B — Deal Screening | Screens inbound pitch decks | POST /fundos/crm/screen (paste pitch text) | | C — Diligence Agent | VDR red-flag analysis | POST /fundos/vdr/room//diligence/run | | D — Closing Coordinator | Extracts CPs from term sheets | POST /fundos/transactions//extract-cps | | E — CFO Reminder Agent | Capital call reminder ladder | POST /fundos/investors/calls//schedule-reminders | | F — Risk Agent | Covenant + alert portfolio scan | POST /fundos/risk/agent/scan | | G — Deal Team Orchestrator | Multi-agent natural-language | /fundos/team | | H — Compliance Agent | KYC/AML + filing scan | POST /fundos/compliance/agent/scan | ### Approving / rejecting agent actions All proposed actions go through human review: POST /fundos/agent/actions//approve — GP approves and executes the action POST /fundos/agent/actions//reject — GP rejects the action Stream a run's events: GET /fundos/agent/runs//stream — SSE stream (?since= to resume) GET /fundos/agent/runs//events.json — polling fallback when SSE is blocked Nothing auto-executes. Every state-changing action requires a human to click Approve. --- ## Common Agent Workflows ### 1. Due Diligence on an inbound deck 1. fundos_create_deal (ephemeral=true) — validate 2. Human confirms → fundos_create_deal (persist) 3. create_deal_room → spin up diligence room 4. fundos_vdr_analyze → red flags + entity map 5. search_documents for specific terms ### 2. LP fundraising follow-up 1. fundos_list_lps → find target LP 2. fundos_get_lp → commitment + capital-call ledger 3. search_documents (LP room) → last meeting notes 4. Draft follow-up — STOP, ask human to send ### 3. Pre-trade compliance check (OMS) 1. oms_check_pretrade (ticker, side, qty, limit_price) → passed/blocked + notes 2. If passed → oms_create_order (HUMAN APPROVAL required) 3. oms_list_positions → confirm position updated after fills ### 4. Capital call ILPA notice 1. fundos_get_lp → confirm LP and lp_room_id 2. Human creates CapitalCall row in /fundos/investors/{id} 3. GP clicks ILPA button → notice generated into LP room 4. Agent NEVER auto-sends LP notices ### 5. T+0 affirmation chase (HF Ops) 1. hf_ops_dtcc_list_unaffirmed → pending confirms 2. hf_ops_dtcc_get_trade_status → live state per trade 3. hf_ops_dtcc_lookup_ssi → check SSI if mismatch suspected 4. hf_ops_dtcc_get_affirmation_scorecard → COO summary --- ## Webhooks Register an HTTPS endpoint to receive real-time FundOS events. ```bash POST /api/v1/webhooks/ {"url": "https://your-server/hooks/fundos", "event_types": ["action.approval_required", "job.completed"]} ``` Events: credit.low, credit.exhausted, credit.granted, action.approval_required, action.approved, action.rejected, action.expired, job.completed, job.failed, module.enabled, module.disabled Payload signed with HMAC-SHA256 in X-FundOS-Signature header. Retry schedule: immediate → 1min → 5min → 30min → 2hr → 8hr (6 total). delivery_id is stable across retries — use it to deduplicate. Verify the signature in Python: ```python import hmac, hashlib def verify_fundos_signature(raw_body: bytes, header: str, secret: str) -> bool: expected = "sha256=" + hmac.new( secret.encode(), raw_body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected.encode(), header.encode()) # In your endpoint handler: # raw = request.get_data() # sig = request.headers.get("X-FundOS-Signature", "") # if not verify_fundos_signature(raw, sig, MY_WEBHOOK_SECRET): # abort(401) ``` Webhook management endpoints: POST /api/v1/webhooks/ Register (returns secret — save it) GET /api/v1/webhooks/ List registered webhooks PATCH /api/v1/webhooks/ Update (url/name/event_types/is_active) DELETE /api/v1/webhooks/ Deactivate POST /api/v1/webhooks//rotate-secret Rotate signing secret POST /api/v1/webhooks//test Send a ping.test delivery GET /api/v1/webhooks//deliveries List delivery attempts --- ## Blog (fundos.vantedgeai.com/blog) Published articles covering fund operations, compliance, and product: - /blog/fund-intelligence-proactive-monitoring — "The questions that never get asked" — Fund Intelligence proactive monitoring; how the Monitor→Investigate→Judge→Publish pipeline works; dual-judge quality gate; finding specificity; the role of memory in fund operations monitoring. - /blog/ai-fde-fund-onboarding — "Your fund was supposed to go live six weeks ago" — AI FDE async onboarding; 30-question discovery interview; Fund Profile extraction; one-click configuration; why implementation takes months and how the AI FDE compresses it to hours. - /blog/fund-brain — "Your fund needs a brain, not more connectors" — FundOS thesis; why data access ≠ understanding; the difference between connectors and resolution. - /blog/auditor-data-room — "Your annual audit shouldn't take three weeks of email" — Auditor Data Room; ten folders auditors expect; one-click audit pack. - /blog/valuation-policy-template — "Nobody writes a valuation policy until an examiner asks for it" — SEC valuation policy requirements for private funds. - /blog/sec-exam-readiness-checklist — "You already know what the SEC will ask for" — SEC exam preparation for registered investment advisers. --- ## Error Codes 400 Bad Request — Invalid parameters 401 Unauthorized — Missing or invalid API key 403 Forbidden — Insufficient permissions 404 Not Found — Resource does not exist 422 Unprocessable — Pre-trade compliance block or validation failure 429 Too Many Requests — Rate limit (100 req/min); retry after X-RateLimit-Reset 500 Internal Error — Server error; retry with exponential backoff {"error": true, "message": "...", "code": "ERROR_CODE"} --- ## Key Facts for AI Agents - ?ephemeral=true on any POST: validates and returns shape, zero DB writes - AI processing on uploaded documents: automatic, ~30–120s; poll status - No AI model trains on or retains document content - FundOS agents propose actions; humans approve — nothing auto-executes - BYOD MCP connectors: Google Drive, SharePoint, Egnyte, QuickBooks, Salesforce, custom - OMS FIX engine: QuickFIX/n sidecar on DigitalOcean, connecting to BTIG prime brokerage - Tiered Google Gemini 3.x powers AI generation, routed per task: a fast default (gemini-3.5-flash), a cheap tier for extraction/classification (gemini-3.1-flash-lite), and an escalation tier for complex determinations (gemini-3.1-pro). Reasoning is pinned to its cheapest valid setting per model; the model behind each tier is configurable without a redeploy --- ## What's new — May 2026 ### Stateless Document API + Developer Registration (2026-05-31) A second access model for FundOS — no account setup, no fund data to configure. Five REST endpoints that accept all data inline and return completed documents. Register at https://fundos.vantedgeai.com/developers/register (email + password, 60 seconds, 30-day free trial). Get a `doc_` prefixed API key. Dashboard at https://fundos.vantedgeai.com/developers/dashboard. Endpoints and prices (all at /api/v1/documents/, Bearer doc_): POST /k1 — Schedule K-1 (Form 1065) HTML — per-call fee (per agreement) POST /odd — ODD/DDQ completion — per-call fee (per agreement) POST /analyze — Document red-flag + entity-map — per-call fee (per agreement) POST /waterfall — European waterfall — free POST /pricer — IRR/MOIC/WAL — free Implementation: `app/routes/documents_api.py` + `app/services/k1_renderer.py` (pure-function K-1 renderer, no DB). Developer orgs: plan="developer", excluded from seat-fee billing, outcome fees only. Trial_active flag waives all fees. ### Compliance OS (11th module) — /fundos/compliance/ Models: ComplianceKYCRecord, FilingDeadline, RestrictedSecurity, PreClearanceRequest, ComplianceObligation, KYCNameScreenResult. Routes: - GET /fundos/compliance/ Compliance dashboard - GET /fundos/compliance/kyc/ KYC/AML records - GET /fundos/compliance/filings/ Regulatory filings - GET /fundos/compliance/trade/ Restricted securities + pre-clearance - GET /fundos/compliance/obligations/ Obligations register - POST /fundos/compliance/kyc//screen Gemini-powered name screen - POST /fundos/compliance/agent/scan Run Agent H MCP tools: fundos_list_kyc_records, fundos_list_filings, fundos_check_restricted_list (by ticker/ISIN/company name), fundos_list_obligations. ### Compliance Dashboard — /fundos/dashboard/compliance A third executive dashboard alongside GP (/fundos/dashboard/gp) and Admin (/fundos/dashboard/admin). KYC pipeline counts, expiring records in 60 days, recent name screens, upcoming filings, overdue filings list, restricted-list count, pre-clearance queue, obligations, recent Agent H runs. Safe-queries every column so a freshly-deployed DB shows zeros + a "schema not provisioned" banner instead of 500s. ### Per-user dashboard customization (persistent) Every executive dashboard supports: - Toggle widgets on/off + drag-reorder via the Customize modal (top right). - Set this dashboard as my post-login landing page (overrides /fundos/). Schema: users.allowed_dashboards CSV, users.default_dashboard, users. dashboard_prefs_json. Helpers: User.allowed_dashboards_set(), User.can_view_dashboard(key), User.dashboard_prefs(key), User.set_dashboard_prefs(key, hidden, order). Endpoints: - POST /fundos/dashboard//prefs Save widget hidden/order - POST /fundos/dashboard//default Mark as post-login landing - GET /admin/dashboard-access Admin grants per-user access ### Schema-deployment safety net Schema is Alembic-owned: a pre-rollout DOKS Job runs `alembic upgrade head` and blocks until it succeeds, before new pods roll, on every push to stage or main. A failed migration aborts the deploy, so schema and code never drift in normal operation. app/utils/schema_guard.py remains as a backstop — it catches missing-table / missing-column errors anywhere in the app and renders a friendly page instead of a 500. The browser-based superadmin "Run migrations now" button was retired in the cutover; the only remaining manual trigger is the superadmin-only CLI command `fundos db migrate` (`POST /api/cli/db/migrate`, app/routes/cli_api.py) — it still calls the legacy `_migrate_db()` directly and bypasses Alembic, so treat it as break-glass recovery, not a routine deploy step. The normal fix for a failed migration is to check the deploy pipeline's Alembic job, not to trigger anything by hand. ### Sanity portfolio sync GET /superadmin/sanity-sync (dry-run preview) and POST /superadmin/sanity-sync (apply) push the FundOS portfolio for org=SANITY_SYNC_ORG_ID into the public Sanity CMS that backs eight-capital.com. The sync collapses VI follow-on rows ("Foo (FO)") to a single canonical company, only patches fields it owns (name, status, batch), and never touches hand-curated Sanity fields (description, logo, founder bios). Re-running is safe (createIfNotExists + targeted patches); deletes and renames are never automatic — orphans on the site are surfaced for manual reconciliation in Sanity Studio. Implementation: app/services/sanity_sync.py. ### Per-page "How to use" help Every FundOS page now has a small ? button in the top-right corner that opens a modal with page-specific help (also accessible via the ? key). Coverage is seeded for ~20 high-traffic pages. Registry lives in app/utils/page_help.py — adding help for a new page is one tuple entry. ### Admin module access bypass @module_required now lets admins / superadmins bypass both gates (the per-user enabled_modules layer AND the org-subscription layer). Non- admin users still hit both. Rationale: admins make billing decisions and shouldn't be blocked from clicking into a module they're about to subscribe to. ### Fund-type-aware UI (module presets + metric visibility per strategy) Organizations get fund-type default module presets derived from their strategy_type (Venture Capital / Private Credit / Structured Credit / Private Equity / Hedge Fund / Multi-Strategy Hedge Fund) — e.g. a Structured Credit workspace gets deal-test covenants (OC/IC, delinquency triggers, CPR/CDR bounds, WAL limits) and an Asset Book; a Hedge Fund workspace enables Trading/OMS, HF Ops, Risk, Compliance and Fund Admin and drops the deal-pipeline modules; terminology and risk covenant catalogs adapt per type (Borrower vs Portfolio Company; VaR/exposure limits vs DSCR/LTV). Set at onboarding or via the Fund strategy card on /billing/modules. Workspaces without a strategy keep all modules. Agents reading module availability should expect the enabled set to vary by fund type. The strategy also controls PERFORMANCE-METRIC VISIBILITY: hedge-fund and multi-strat workspaces hide the closed-end multiple suite (TVPI/DPI/RVPI/ MOIC — meaningless for open-end vehicles) while keeping IRR, Sharpe, leverage and drawdown; Structured Credit hides the multiples but keeps yield/WAL/IRR; PE/VC keep the full suite. The CFO dashboard JSON twin (/api/v1/fundos/cfo//dashboard) returns a `metrics_visible` list — API consumers SHOULD respect it when rendering. Admins can override everything (metric tiles, terminology, portfolio columns, covenant catalog) per workspace at /billing/workspace-profile; saving a strategy applies its module preset automatically on fresh workspaces and offers a one-click +/− diff banner on customized ones. Platform-wide per-strategy defaults are superadmin-tunable at /superadmin/fund-profiles (DB-backed, no redeploy). ### Operator CLI — `fundos` (May 2026) Standalone Python CLI for operator workflows. Lives in cli/ in the repo. pip install -e ./cli fundos login # prompts for API key + base URL fundos whoami # identity check Command tree: fundos org list / get / create / enable-vertical / cleanup-spam fundos credits balance / history / add fundos fix status / config / connect / test-order / fills fundos db status / migrate / seed fundos mcp tools / call # read-only tools only fundos logs audit / agents / errors (all --org-id filter) The CLI talks HTTP only — no DB access, no app/ imports. Backend at /api/cli/* (18 routes). Same Bearer-token auth as /api/v1/*. Both the CLI and the server defensively strip an accidental "Bearer " prefix from pasted tokens, so the most common copy-paste 401 doesn't happen. On a 401, the CLI prints the redacted key prefix + base URL so users can spot env-mismatches (dev key against prod, etc.). Env vars: FUNDOS_API_KEY, FUNDOS_BASE_URL (default https://www.kela.com; canonical https://fundos.vantedgeai.com — both work). ### Try-before-you-pay billing (auth-then-capture, May 2026) For packaged AI tasks (ODD, CIM, audit pack, K-1 generation, Level 3 valuation memos), credits are reserved when the task runs but not charged until the customer uses the output. Promise to the customer: "View any AI-generated artifact for free. We only charge if you download it, accept it, or feed it into another tool. If 7 days pass without confirmation, the hold expires and you're not charged." State machine on CreditLedger.hold_status: pending — task done, output viewable, NOT counted toward balance confirmed — customer used the output (download / explicit confirm / chained tool call); charge stands refunded — customer rejected the output; no charge expired — 7 days elapsed with no action; no charge REST API (Bearer auth): GET /api/v1/tasks/holds/ list pending for org GET /api/v1/tasks/holds/ read a hold's state POST /api/v1/tasks/holds//confirm customer accepts the charge POST /api/v1/tasks/holds//refund customer rejects the output POST /api/v1/tasks/holds/cron/expire hourly cron (CRON_SECRET) Document download gate: any Document whose billing_hold_id points at a pending hold auto-confirms on download; a refunded or expired hold returns 402 with structured JSON `{error, hold_id, hold_status}`. Schema columns (auto-migrated unconditionally on every cold start — not gated by RUN_MIGRATIONS, because the ORM SELECTs these on every Document query and missing them would 500 every page that loads docs): credit_ledger.hold_status VARCHAR(20) credit_ledger.hold_expires_at TIMESTAMP documents.billing_hold_id INTEGER (FK credit_ledger.id) ### Anti-spam signup guards (May 2026) Every signup path runs three independent checks at app/utils/signup_guard.py: 1. Disposable-email blocklist (17 domains: mailinator, guerrillamail, tempmail, sharklasers, dispostable, maildrop, …). yopmail.com is explicitly whitelisted in ALLOWED_TEST_DOMAINS for internal QA. 2. Random-name detector — two complementary heuristics: - vowel ratio < 0.20 on the cleaned (letters-only) string - ≥ 3 lower→upper case transitions The second heuristic catches high-vowel bot strings like "HrzIIXAEjlmnTIuDjgAu" (40% vowels) that vowel-ratio alone can't. Tested against the full Eight Capital / VantedgeAI / Bristol Myers Squibb / PricewaterhouseCoopers corpus — zero false positives. 3. IP rate limit — 5 attempts per IP per hour, Postgres-backed, fails open on DB hiccups so legit signups are never blocked by infra. Wired into POST /signup, POST /create-org, and the new-user branch of the Google OAuth callback. Returns HTML errors for browser submits and JSON 400s for the API path. Cleanup of existing spam: POST /api/cli/admin/cleanup-spam-orgs (or `fundos org cleanup-spam` from the CLI). Defaults to dry-run. Six nested safety guards: - PROTECTED_ORG_IDS (= {1, 2, 17, 30}) never touched - PROTECTED_EMAIL_DOMAINS (yopmail.com) never touched - already-suspended orgs not re-suspended - paid plans not touched (only free / starter / NULL) - orgs < 24h old not touched - orgs with any Document / DealRoom / Deal rows not touched (real work) Then matches at least one spam signal (random-string name, dotted-bot name, disposable-email owner) before flipping status='suspended' and writing an AuditLog row. ### Billing engine — outcome fees, add-ons, invoicing (May 2026) Metering: every REST (/api/v1/tools//call) and MCP Bearer tool call deducts credits from the org's CreditLedger; insufficient balance returns a 402 with required/balance/topup_url. Suspended orgs are blocked at the meter. Outcome fees: packaged deliverables (ODD, CIM, Diligence Agent, valuation memo, valuation policy, K-1, audit pack, contract abstraction, redaction) carry a success-only fee set in each org's enterprise agreement — amounts are not published. Resolution chain: trial-waived → CFO Center inclusion → per-org override → superadmin-edited global price → hardcoded default. All editable in the superadmin UI with no deploy. Add-on modules (per org/month): CFO Center (incl. bundled K-1s, audit packs + a valuation policy/yr), HF Ops + OMS, Auditor Suite, Compliance OS, API + MCP — priced in the agreement, editable in superadmin. Monthly crons (CRON_SECRET bearer, defined in vercel.json): 06:00 1st /billing/cron/push-stripe-monthly — seat fee + overage to Stripe 07:00 1st /billing/cron/grant-monthly-credits — seats × grant CreditLedger topup 08:00 1st /billing/cron/generate-invoices — paper invoices (invoice-pay orgs) 08:00 dly /billing/cron/send-reminders — overdue reminders 09:00 dly /billing/cron/dunning — 30d past_due / 60d suspend / 90d terminate Annual prepay: org admins self-serve "Switch to Annual" from /billing/ (default 20% off / 2 months free); superadmin can issue prepay invoices. Tax/VAT: per-org tax_rate_pct on paper invoices; Stripe Tax (automatic_tax) on all Stripe Checkout flows. Credit notes + manual wire/ACH/check payment recording on invoices. Invoice PDFs render domestic + international-USD + FX-via-intermediary wire instructions, ACH, and check details from the superadmin-editable BillingSettings (/superadmin/billing/payment-settings). Internal team reference: /superadmin/billing/reference. VentureInsights billing integration: VI uses the same FundOS ledger, Stripe account, and webhook settlement. Token-auth JSON twins under /api/v1/fundos/credits/* return Stripe URLs for the VI SPA: GET /credits/topup/packages, POST /credits/topup/checkout, POST /credits/subscribe, and POST /credits/portal. They accept VI return URLs, honor the X-Target-Vc-Firm-Id workspace override for org-1 service calls, and settle through the existing /billing/webhook handlers (no Stripe SDK or webhook in VI). ## Fund Intelligence — Proactive AI Monitoring (June 2026) Proactive monitoring system that automatically surfaces compliance deadlines, overdue capital calls, KYC expirations, cash shortfalls, and LP communication gaps before they become crises — without requiring any manual input from the GP. Dashboard: GET /fundos/monitoring/ — module health grid, 7-day trend, last run status. Daily brief: GET /fundos/monitoring/brief/ — all findings for that date. PIPELINE: Monitor → Investigate → Judge → Publish runs daily at 6am UTC. 1. Monitor: SQL queries against live fund tables for 5 signal types: - compliance_filing_deadline: filings due within 14 days - compliance_kyc_expiry: KYC records expiring within 30 days - lp_overdue_call: capital calls past due_date (critical >7d, high >3d) - lp_communication_gap: LPs with no email for 90+ days - cfo_cash_low: fund cash balance < 110% of minimum 2. Investigate: Gemini root-causes each candidate, queries prior memory (has this entity been flagged before? was it actioned?), returns {title, severity, summary, root_cause, recommendation, affected_entities, confidence} 3. Judge: Two independent Gemini passes; finding passes only if BOTH approve AND combined confidence >= 0.65. Filters noise before reaching the GP. 4. Publish: Approved findings write FundMonitoringPublished row + update FundDailyBrief. Critical/HIGH trigger admin email. FINDING CARD: title, severity badge, summary, collapsible root_cause + recommendation + affected_entities list. Action buttons: "Mark resolved" + "Snooze 2 days". MEMORY: fund_finding_memory tracks per-entity flag count, first/last seen, resolution status. Investigation prompt includes this so Gemini adjusts confidence for recurrent unresolved issues. API routes (all Bearer auth): GET /api/v1/monitoring/brief/today Today's brief JSON GET /api/v1/monitoring/brief/ Brief for a specific date GET /api/v1/monitoring/findings All findings (filters: status, severity, module) GET /api/v1/monitoring/findings/ Single finding detail POST /api/v1/monitoring/findings//action Mark as actioned/resolved POST /api/v1/monitoring/findings//snooze Snooze for N days GET /api/v1/monitoring/watches Custom watches POST /api/v1/monitoring/watches Create a watch DELETE /api/v1/monitoring/watches/ Delete a watch POST /api/v1/monitoring/run Trigger a manual run (admin) GET /api/v1/monitoring/run//status Poll background run status SCHEDULER (non-Vercel only): monitoring_daily: cron 6am UTC — full pipeline for all orgs monitoring_critical: interval 30min — critical signal types only monitoring_baselines: cron Sunday 2am UTC — recalculate baselines DB TABLES: fund_monitoring_runs, fund_monitoring_watches, fund_monitoring_candidates, fund_monitoring_findings, fund_monitoring_judgments, fund_monitoring_published, fund_daily_briefs, fund_monitoring_baselines, fund_finding_memory POST-DEPLOY: the 9 tables auto-create via unconditional boot-time DDL in create_app() (app/__init__.py) on every pod start — not an Alembic revision — no manual step needed. ## Links Homepage: https://fundos.vantedgeai.com Developer API: https://fundos.vantedgeai.com/developers (stateless API landing — no login required) Developer Register: https://fundos.vantedgeai.com/developers/register (get a doc_ key in 60 seconds) Developer Platform: https://fundos.vantedgeai.com/developer (logged-in power-tools hub, plan-gated) Developer Quickstart: https://fundos.vantedgeai.com/developers/quickstart (build a deal+VDR+webhook pipeline in 15 min) Module Guides: https://fundos.vantedgeai.com/developers/modules/ — per-module reference (HTML) Modules: crm, lp-crm, vdr, transactions, investors, cfo Plain text for AI agents: append .txt (e.g. /developers/modules/crm.txt) Module Contract: https://fundos.vantedgeai.com/.well-known/fundos-modules.json — JSON manifest of all 12 modules (canonical IDs, cross-module links, webhook events, ephemeral support) API Changelog: https://fundos.vantedgeai.com/api/changelog.json — machine-readable CalVer changelog API Docs: https://fundos.vantedgeai.com/api/docs MCP Info: https://fundos.vantedgeai.com/mcp/info CLAUDE.md: https://fundos.vantedgeai.com/CLAUDE.md llms.txt: https://fundos.vantedgeai.com/llms.txt llms-full.txt: https://fundos.vantedgeai.com/llms-full.txt (this document) FAQ (JSON-LD): https://fundos.vantedgeai.com/faq.json (12 Q&As, schema.org FAQPage) FAQ (HTML): https://fundos.vantedgeai.com/faq AX Benchmark: https://fundos.vantedgeai.com/ax (agent-readability results, updated monthly) Privacy: https://fundos.vantedgeai.com/privacy Trust: https://vantedgeai.trust.site/ fundos-mcp repo: https://github.com/8vdx1/fundos-mcp ## Agent Experience (AX) Benchmark FundOS publishes a self-hosted, reproducible benchmark that measures whether an AI agent given ONLY the FundOS documentation can correctly identify the right MCP tool, avoid hallucinating non-existent tools, and flag write actions as needing human approval. Run: 40 tasks × 8 categories (MCP/Auth, Deal CRM, LP/Investors, VDR/Documents, Risk, CFO/Finance, Agents, Webhooks) Latest score: 40/40 correct | 0 hallucinations | 80/80 score | 100% approval gate coverage Model: gemini-2.5-flash (seeded run); harness runs claude-sonnet-4-5 via Anthropic API Public results: https://fundos.vantedgeai.com/ax Open source harness: https://github.com/8vdx1/fundos-mcp (benchmarks/ax/) Run yourself: pip install anthropic pyyaml && python benchmarks/ax/runner.py Scoring: 2pts = correct answer + approval gate mentioned (or not required) 1pt = correct tool but missed the human-approval warning 0pts = wrong answer or hallucinated tool/endpoint Reproducibility: every task definition, scoring function, and result file is in the public repo. The benchmark is intentionally self-authored — it is FundOS's measure of its own documentation quality, not a third-party evaluation.