FundOS API Reference

Every FundOS module is callable standalone via Bearer-authenticated REST. Inline data, Kela-hosted rows, or MCP BYOD sources — your choice per call.

Authentication

Every endpoint requires a Bearer token — either a JWT (24-hour, from POST /api/v1/auth/login) or a long-lived API key (prefix vdr_, generated in Admin → API Keys).

curl -H "Authorization: Bearer vdr_your_api_key" \
     -H "Content-Type: application/json" \
     https://my-vdr.vercel.app/api/v1/fundos/crm/deals
Rate limit: 100 req/min per token. Responses include X-RateLimit-Remaining and X-RateLimit-Reset headers.
Conventions
  • Three data modes: Kela-hosted (default), Headless (inline data in payload), BYOD (MCP connection reference).
  • ?ephemeral=true: any POST endpoint that normally persists a row will instead validate and return the response shape with persisted: false.
  • Org-scoped: every call runs in the caller's organisation context — no cross-tenant access.
  • BYOD source schema: {"type": "mcp", "connection_id": N, "path": "..."} or {"type": "inline", "documents": [{"name": "...", "text": "..."}]}.

CRM & Pipeline

Deal sourcing, pipeline management, contacts, and activity log.
8 endpoints
GET /api/v1/fundos/crm/deals ?stage=<key>
List deals in your organisation.
GET /api/v1/fundos/crm/pipeline
Deals grouped by stage — kanban shape.
POST /api/v1/fundos/crm/deals
Create a deal. `?ephemeral=true` validates + returns without persisting.
{
  "asset_class": "private_credit",
  "counterparty": "ACME Capital",
  "currency": "USD",
  "irr_target": 0.12,
  "name": "Fund II \u2014 ACME Credit",
  "stage": "dd",
  "target_size": 25000000
}
GET /api/v1/fundos/crm/deals/{id}
Fetch a single deal.
PATCH /api/v1/fundos/crm/deals/{id}
Update any subset of deal fields.
POST /api/v1/fundos/crm/deals/{id}/stage
Move the deal to a new pipeline stage.
{
  "stage": "closing"
}
POST /api/v1/fundos/crm/deals/{id}/activity
Log an activity on the deal.
{
  "summary": "Called sponsor about term sheet.",
  "type": "note"
}
POST /api/v1/fundos/crm/deals/{id}/contacts
Add a contact to the deal.
{
  "email": "jane@example.com",
  "name": "Jane Doe",
  "role": "Sponsor CFO"
}

VDR + DD Agent

BYOD-capable ODD generation and VDR analysis. Data can stay in your MCP server.
2 endpoints
POST /api/v1/fundos/odd/generate
Generate ODD answers from inline docs or an MCP BYOD source.
{
  "ephemeral": true,
  "source": {
    "connection_id": 5,
    "path": "/Funds/FundII/DD",
    "type": "mcp"
  },
  "topics": [
    "key_data",
    "fund_terms"
  ]
}
Default ephemeral=true — outputs never persisted.
POST /api/v1/fundos/vdr/analyze
Red-flag + entity-map analysis over inline docs or MCP source.
{
  "ephemeral": true,
  "source": {
    "documents": [
      {
        "name": "ppm.pdf",
        "text": "\u2026"
      }
    ],
    "type": "inline"
  }
}

Transaction Manager

Term sheets, closing coordination, signatory tracking.
6 endpoints
GET /api/v1/fundos/transactions
List transactions. `?status=<key>` filter.
GET /api/v1/fundos/transactions/{id}
Fetch transaction + task pack.
POST /api/v1/fundos/transactions/draft
Draft a new transaction. Auto-seeds default closing task pack.
{
  "asset_class": "private_credit",
  "deal_id": 123,
  "linked_room_id": 45,
  "name": "FundII \u2014 ACME Credit closing",
  "parties": [
    {
      "name": "ACME Capital",
      "role": "Lender"
    }
  ],
  "seed_default_tasks": true,
  "target_close_date": "2026-06-15"
}
POST /api/v1/fundos/transactions/{id}/status
Update transaction status (drafting → negotiating → signed → funding → closed).
{
  "status": "signed"
}
POST /api/v1/fundos/transactions/{id}/tasks
Add a task to the transaction.
{
  "category": "legal",
  "title": "Final IC approval"
}
PATCH /api/v1/fundos/transactions/{id}/tasks/{task_id}
Update task status / title / due date.
{
  "status": "complete"
}

Pricer + Pool Analytics

Pricing, IRR/MOIC/WAL, waterfall, optional tranche stack.
1 endpoints
POST /api/v1/fundos/pricer/run
Run pricing for a principal + term. Pure-Python, deterministic.
{
  "amortisation": "bullet",
  "benchmark_pct": 0.04,
  "ceiling_pct": 0.12,
  "coupon_pct": 0.08,
  "deal_id": 123,
  "fees_upfront_pct": 0.01,
  "floor_pct": 0.07,
  "principal": 10000000,
  "spread_bps": 400,
  "term_months": 60,
  "tranches": [
    {
      "balance": 7000000,
      "coupon_pct": 0.06,
      "name": "Senior A",
      "priority": 1
    }
  ]
}
Without `deal_id`, nothing is persisted. `?ephemeral=true` forces no persistence.

DSRI Risk Intelligence

Real-time covenant monitoring, breach simulation, alerts.
3 endpoints
GET /api/v1/fundos/risk/covenants
List all tracked covenants with current status.
POST /api/v1/fundos/risk/check
Simulate (inline) or refresh (by covenant_id) a covenant check.
{
  "covenant_id": 7,
  "current_value": 1.05
}
Omit covenant_id to run an ephemeral simulation with inline {name,type,direction,threshold,current_value}.
GET /api/v1/fundos/risk/alerts
List risk alerts. `?open=true` for only unresolved.

CIM / Report Builder

AI-synthesised investment memoranda. MCP BYOD supported.
4 endpoints
GET /api/v1/fundos/cim/templates
List available templates (standard, teaser, onepager).
GET /api/v1/fundos/cim/reports
List generated CIM reports in your org.
GET /api/v1/fundos/cim/reports/{id}
Fetch full CIM report with all sections.
POST /api/v1/fundos/cim/generate
Generate a CIM from inline docs or MCP source.
{
  "deal_id": 42,
  "source": {
    "connection_id": 5,
    "path": "/Funds/Fund II",
    "type": "mcp"
  },
  "template_key": "standard",
  "title": "Fund II \u2014 IC Memo"
}

Investor Portal

LP registry, commitments, capital calls.
5 endpoints
GET /api/v1/fundos/investors/lp
List LP investors.
POST /api/v1/fundos/investors/lp
Register an LP investor.
{
  "committed_capital": 10000000,
  "entity_type": "family_office",
  "jurisdiction": "DE",
  "kyc_status": "pending",
  "name": "Cascade Family Office",
  "primary_contact_email": "ir@cascade.example"
}
GET /api/v1/fundos/investors/lp/{id}
Fetch an LP plus their capital calls.
POST /api/v1/fundos/investors/lp/{id}/capital-calls
Issue a capital call to an LP.
{
  "amount": 500000,
  "due_date": "2026-05-15",
  "notice_date": "2026-04-20",
  "reference": "CC-2026-Q2-01",
  "status": "issued"
}
GET /api/v1/fundos/investors/capital-calls
List all capital calls across LPs. `?status=<key>` filter.

CFO Center

Fund accounts, P&L roll-ups, European waterfall.
5 endpoints
GET /api/v1/fundos/cfo/accounts
List fund accounts / SPVs with NAV.
POST /api/v1/fundos/cfo/accounts
Create a new fund account.
{
  "committed_total": 100000000,
  "currency": "USD",
  "entity_type": "fund",
  "fiscal_year_end": "12-31",
  "gl_provider": "manual",
  "name": "Fund II \u2014 Main"
}
POST /api/v1/fundos/cfo/accounts/{id}/entries
Record a journal entry against a fund account.
{
  "category": "expense",
  "credit": 45000,
  "date": "2026-04-15",
  "debit": 0,
  "description": "Legal fees \u2014 Fund II closing",
  "reference": "JE-2026-Q2-07"
}
POST /api/v1/fundos/cfo/report
Compute P&L + NAV for an account or inline entries (headless).
{
  "end": "2026-12-31",
  "fund_account_id": 1,
  "start": "2026-01-01"
}
Send `entries: [...]` instead of `fund_account_id` for headless BYOD math (no persistence).
POST /api/v1/fundos/cfo/waterfall
Pure-Python European waterfall (ROC → hurdle → catch-up → carry split).
{
  "carry_pct": 0.2,
  "committed": 100000000,
  "distributable": 140000000,
  "hurdle_pct": 0.08
}

Syndication Engine

Multi-investor allocation matrix, KYC tracking, funds-flow status.
4 endpoints
GET /api/v1/fundos/syndication
List all syndications in your org.
POST /api/v1/fundos/syndication
Create a new syndication.
{
  "closing_date": "2026-06-30",
  "currency": "USD",
  "lead_arranger": "Kela Capital",
  "name": "Deal X \u2014 Co-invest round",
  "status": "building",
  "target_amount": 25000000
}
GET /api/v1/fundos/syndication/{id}
Fetch a syndication with full allocation matrix.
POST /api/v1/fundos/syndication/{id}/allocate
Create one or many allocations. Send single object or {allocations: [...]}.
{
  "allocations": [
    {
      "allocated_amount": 4500000,
      "funds_status": "signed",
      "investor_name": "Cascade FO",
      "kyc_status": "passed",
      "requested_amount": 5000000
    },
    {
      "allocated_amount": 7500000,
      "kyc_status": "pending",
      "lp_investor_id": 12
    }
  ]
}

Agent Runtime & Tool Registry

AgentRun substrate + approve/reject surface + catalog of 14 tools exposed as Gemini function declarations or REST.
10 endpoints
GET /api/v1/tools
List all registered tools. Each entry includes name, description, Pydantic args schema.
Filter with ?category=lp_crm|crm|vdr|cfo|risk
GET /api/v1/tools/gemini-declarations
Return Gemini-ready `functionDeclarations`. Pass straight into generateContent(tools=[...]).
?names=lp_crm.add_todo,crm.advance_stage to scope.
GET /api/v1/tools/{name}
Get one tool's spec.
POST /api/v1/tools/{name}/call
Invoke a tool directly. Body = validated input; returns {tool, result}.
{
  "lp_investor_id": 12,
  "title": "Send Q3 letter"
}
GET /fundos/agent/
List recent AgentRuns (admin/debug).
GET /fundos/agent/runs/{run_id}
Run detail page — live SSE event feed + approval cards.
GET /fundos/agent/runs/{run_id}/stream
Server-Sent Events stream. ?since=<event_id> for resume.
Vercel 45s budget; emits `timeout` event with resume_from when exhausted so clients reconnect.
GET /fundos/agent/runs/{run_id}/events.json
Polling fallback (same ?since= semantics). Used when SSE is blocked by corp proxy.
POST /fundos/agent/actions/{action_id}/approve
Approve a proposed AgentAction and execute its registered handler.
POST /fundos/agent/actions/{action_id}/reject
Reject a proposed AgentAction with optional reason.
{
  "reason": "Wrong stage"
}

FundOS Copilot

Context-aware chat answer endpoint for the right-side sidebar.
1 endpoints
POST /fundos/copilot/ask
Ask a question with optional context hints. RAG-grounded with citations.
{
  "context": {
    "deal_id": 42,
    "scope_label": "deal Acme"
  },
  "history": [
    {
      "role": "user",
      "text": "..."
    },
    {
      "role": "assistant",
      "text": "..."
    }
  ],
  "question": "What is the target net IRR?"
}
Scope ladder: lp_id → room_id → deal_id → org-wide.

VentureInsights Integration

Inbound webhooks from VI → Kela, outbound webhooks from Kela → subscribers, backfill imports, nightly reconciliation, and the federated VIClient that reads live VI data at feature-compute time.
8 endpoints
POST /webhooks/vi/{event_type}
Inbound webhook receiver. CSRF-exempt; HMAC-SHA256 is the auth.
Required headers: X-VI-Event, X-VI-Event-Id, X-VI-Timestamp, X-VI-Signature, X-VI-Connection. Signature = hex(HMAC-SHA256(secret, '<ts>.<raw body>')). 300s skew window. Idempotency via UNIQUE(event_id). Types: company.created/.updated/.deleted, fund.created/.updated/.deleted, ping.test.
GET /webhooks/vi/_health
Simple live-check endpoint for VI admins to sanity-check the URL.
POST /webhooks/vi/cron/reconcile
Nightly reconciler — catches webhook events that failed all 5 retries on VI side.
Protected by CRON_SECRET Bearer token. Runs 0 3 * * * UTC via Vercel cron. Safe to invoke manually for debugging.
POST /admin/integrations/ventureinsights
Admin: save VI connection (NestJS base, analytics base, agent MCP URL, X-API-KEY, enabled modules).
POST /admin/integrations/ventureinsights/test
Live health check — pings each configured upstream, returns {nestjs, analytics, mcp} status.
POST /admin/integrations/ventureinsights/rotate-webhook-secret
Generate a fresh HMAC secret for inbound webhooks. Returned PLAINTEXT ONCE in the flash + ?_show_secret redirect.
POST /admin/integrations/ventureinsights/import/companies
Bulk backfill VI Companies → Deal CRM. Logs a VIImportRun row.
POST /admin/integrations/ventureinsights/import/funds
Bulk backfill VI Funds → LP CRM. Logs a VIImportRun row.

Outbound Webhooks (Kela → subscribers)

Kela emits HMAC-signed events to any configured WebhookEndpoint. Used by the VentureInsights reverse direction, Zapier, Make, and custom consumers.
2 endpoints
GET /developer/connected-apps
Admin UI — list / create / revoke / retry webhook endpoints.
POST /developer/connected-apps
Create a webhook endpoint. Subscribe to specific events.
{
  "events": [
    "odd.profile.updated",
    "answer_bank.updated",
    "room.red_flag.added"
  ],
  "name": "VentureInsights reverse",
  "url": "https://stage-api.8vdx.io/webhooks/kela"
}
Event catalogue
EventTriggerPayload sample
odd.profile.updated FundProfile save (fund_name / vintage / fees / strategy / team / etc.)
{
  "fund_name": "Acme II",
  "fund_profile_id": 1,
  "updated_at": "...",
  "vintage_year": 2026
}
answer_bank.updated sync_fund_profile() touches rows
{
  "fund_profile_id": 1,
  "source_type": "manual",
  "touched": 3
}
room.red_flag.added Intelligence red-flag scanner inserts a RedFlag row
{
  "category": "legal",
  "red_flag_id": 42,
  "room_id": 5,
  "severity": "high",
  "title": "..."
}
Signing: Every delivery carries X-Kela-Event / X-Kela-Timestamp / X-Kela-Signature headers. Signature = hex(HMAC-SHA256(endpoint.secret, '<ts>.<body>')). Receivers should verify signature AND reject timestamps more than 5 minutes off their clock.

MCP Connector Catalogue

These connectors are consumed by FundOS via the Model Context Protocol. In BYOD mode, your data never leaves your own MCP server — Kela reads in-memory and persists only outputs. Configure in Settings → MCP Connections.

Connector Kind Modes Used by Notes
SharePoint documents BYOD VDR, ODD, CIM OAuth to your tenant; docs stay in SharePoint, Kela reads in-memory.
Egnyte documents BYOD VDR, ODD, CIM
Google Drive documents BYOD VDR, ODD, CIM
Dropbox documents BYOD VDR, ODD, CIM
Salesforce crm BYOD CRM
HubSpot crm BYOD CRM
Affinity crm BYOD CRM
DocuSign e-sign BYOD Transactions
QuickBooks accounting BYOD CFO
Xero accounting BYOD CFO
Sage Intacct accounting BYOD CFO
Bloomberg market data BYOD Pricer, Risk
VentureInsights private-markets data BYOD CRM, Investors, CIM, Risk Funds, companies, LPs, deals. VI consumes Kela's MCP server in reverse.
MCP Setup Quick Start
  1. Go to Settings → MCP Connections and click Add connection.
  2. Enter the server URL (HTTPS, SSE, or stdio command) and pick the modules that should use this source.
  3. Toggle BYOD mode if source documents should never be stored in Kela — outputs only.
  4. Kela will run a health check. Healthy connections appear as source options inside each module's UI and API.
  5. In API calls, reference the connection via {"type": "mcp", "connection_id": N, "path": "..."}.