# Invisible Cap Table — Product Guide ## What is Invisible Cap Table? Invisible Cap Table is an AI-native cap table management system. Unlike traditional cap table software with dashboards, forms, and complex menus, Invisible is a pure chat interface. You talk to it in plain English to manage your company's equity — view ownership, record transactions, manage option grants, invite stakeholders, and prepare for Board meetings. There is no UI to learn. Just describe what you need, and the AI handles the rest. ## Who is it for? - **Founders & CEOs** — Full visibility and control over your cap table - **CFOs & Finance Teams** — Record transactions, manage equity plans, prepare Board materials - **Investors** — View your holdings and cap table position across portfolio companies - **Employees** — See your equity grants, vesting schedules, and exercise options - **Lawyers & Accountants** — Read-only access to cap table data for audits and compliance ## How it works 1. **Sign up** — Create an account at invisible.app 2. **Create an organization** — Set up your company 3. **Load your cap table** — Tell the assistant about your stakeholders, funding rounds, and option grants. You can describe them conversationally or upload a spreadsheet. 4. **Manage everything through chat** — Ask questions, record new transactions, generate reports, invite team members. ## Capabilities ### View & Analyze - **Full cap table** — See all stakeholders, share classes, ownership percentages, fully diluted breakdown - **Stakeholder detail** — Holdings, transaction history, option grants for any stakeholder - **Option grants** — Vesting status, exercise prices, expiration dates, with as-of-date calculations - **Security classes** — All preferred series with economic terms (OIP, liquidation preferences, conversion ratios, seniority) - **Transaction history** — Complete ledger of all equity transactions with filters ### Manage Equity - **Record transactions** — Issuances, transfers, exercises, cancellations, conversions - **Manage option grants** — Create grants with vesting schedules, track through approval workflow (proposed → pending approval → approved → active) - **Grant categories** — Tag grants as new hire, promotion, retention, performance, refresh, or advisory - **Update terms** — Modify conversion ratios (for anti-dilution ratchets), authorized shares, OIP - **Equity plans** — Create and manage incentive plans with authorized share pools ### Organize & Report - **Investor groups** — Group stakeholders for Board reporting rollups - **Security class summaries** — Breakdown by class with economic terms - **Ownership analysis** — Fully diluted ownership with as-converted calculations ### Team Management - **Invite team members** — Add admins, finance team, lawyers with appropriate access levels - **Invite stakeholders** — Send invite codes to investors and employees to view their own holdings - **Role-based access** — Owners and Admins can manage everything; Viewers see the cap table; Employees see only their own grants ### Visibility & Org Hierarchy - **Manager hierarchy** — Set reporting relationships between stakeholders. Managers automatically see equity data for their full report tree (direct and indirect reports). - **Department-based access** — Grant users view access to all equity data in specific departments, without being in the manager chain. Perfect for RevOps, HR, or finance roles. - **Granular middle ground** — Between "own holdings only" and "full cap table" access, managers and department-access users see exactly the subset they need. - **Bulk org chart import** — Set manager relationships in bulk via AI, including integration with HR tools like Levitate. ## Common Workflows ### "I just closed a funding round" 1. Tell the assistant about the new series (name, price per share, authorized shares, terms) 2. List the investors and their share amounts 3. The assistant creates the security class, stakeholders, and records the issuance transactions 4. View the updated cap table to confirm ### "I need to issue new option grants" 1. Tell the assistant who's getting grants, how many shares, exercise price, and vesting terms 2. The assistant creates the grants in "proposed" status 3. Review the grants and approve them (or present to the Board first) 4. Once approved, update status to "active" ### "I want to invite an investor to see their holdings" 1. Ask the assistant to invite the stakeholder by email 2. The assistant generates an invite code 3. Share the code with the investor 4. They sign up, enter the code, and can see their holdings ### "I need to prepare for a Board meeting" 1. Ask for a cap table summary 2. Ask about the option pool — how many shares authorized, outstanding, available 3. Review any pending option grants that need Board approval 4. Ask for an ownership breakdown by investor group ### "Our latest round had anti-dilution protection" 1. Tell the assistant the new conversion ratio for the affected series 2. The assistant updates the security class 3. View the cap table to see the as-converted impact ### "I want managers to see their team's equity" 1. Set up the org hierarchy: tell the assistant who reports to whom (or bulk-import from your HR system) 2. Each manager (when they log in as a viewer or employee) automatically sees equity data for their full report tree 3. To give a RevOps or HR person department-wide access, grant them department access (e.g., "Give Maria access to all Sales department equity data") 4. Admins control all visibility settings — managers cannot escalate their own access ## Access Levels | Role | Can View | Can Edit | Can Invite | |------|----------|----------|------------| | **Owner** | Everything | Everything | Yes | | **Admin** | Everything | Everything | Yes | | **Member** | Everything | Cap table data | No | | **Viewer** | Full cap table OR own holdings only (configurable) | Nothing | No | | **Employee** | Own grants and holdings only | Nothing | No | **Visibility modifiers** (apply to Viewers and Employees): - **Manager hierarchy** — If a viewer/employee has direct or indirect reports, they also see those reports' equity data - **Department access** — Admins can grant a user view access to all stakeholders in specific departments - These combine: a user with manager access AND department access sees the union of both sets ## Glossary - **Fully Diluted** — Total shares counting all outstanding stock, preferred (on an as-converted basis), options, and available option pool - **As-Converted** — Preferred shares converted to common stock equivalent using the conversion ratio - **Anti-Dilution Ratchet** — Adjusts a preferred series' conversion ratio when a subsequent round is priced lower (down round) - **409A Valuation** — Independent appraisal of common stock fair market value, used to set option exercise prices - **Vesting** — Schedule by which equity is earned over time (typically 4 years with a 1-year cliff) - **Cliff** — Initial period before any equity vests (typically 12 months) - **ISO** — Incentive Stock Option, tax-advantaged for employees - **NQSO** — Non-Qualified Stock Option, used for contractors and advisors - **RSU** — Restricted Stock Unit, a promise to issue shares upon vesting - **Liquidation Preference** — Priority claim on proceeds in an exit event (typically 1x) - **Participating Preferred** — Gets both liquidation preference AND pro-rata share of remaining proceeds - **Non-Participating Preferred** — Gets the greater of liquidation preference OR as-converted share - **Seniority** — Order in which preferred series get paid in a liquidation event - **Option Pool** — Shares reserved for future equity grants under an incentive plan - **Original Issue Price (OIP)** — Price per share when a preferred series was issued ## Connect Your AI Assistant (MCP Integration) Invisible Cap Table works with any AI assistant that supports the Model Context Protocol (MCP). This means you can query and manage your cap table directly from Claude, or any other MCP-compatible AI tool. ### Claude (claude.ai) **For organization admins — add for your whole team:** 1. Go to your Claude organization settings 2. Navigate to **Connectors** → **Add Custom Connector** 3. Enter the URL: `https://mcp.invisible.app/mcp` 4. Leave OAuth Client ID and Client Secret blank — they're not needed 5. Save the connector Everyone in your Claude org can now enable the Invisible Cap Table connector. When they first use it, they'll be asked to sign in with their invisible.app account. **For individual users — Claude Desktop or Claude Code:** Add this to your MCP configuration: ```json { "mcpServers": { "invisible-cap": { "url": "https://mcp.invisible.app/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY", "X-Organization-Id": "YOUR_ORG_ID" } } } } ``` To get your API key and org ID, ask the assistant at invisible.app: *"Generate an API key for MCP access"* ### Other MCP Clients Any MCP client that supports the Streamable HTTP transport can connect to: - **URL:** `https://mcp.invisible.app/mcp` - **Auth:** Bearer token (API key) or OAuth 2.0 (authorization code + PKCE) ### What can you do via MCP? Everything you can do in the chat, you can do via MCP: - Query the full cap table, stakeholder details, option grants - Record transactions, create grants, exercise options - Look up vesting schedules, security class terms, equity plans - Manage stakeholders and investor groups The AI tools respect the same role-based permissions as the chat interface. ## 409A Valuations Invisible Cap Table includes a built-in 409A valuation engine. A 409A valuation determines the fair market value (FMV) of your company's common stock, which is required to set exercise prices for stock option grants. Without a defensible 409A, your employees risk adverse tax consequences under IRC Section 409A. ### Two tiers **AI-Only (self-serve):** Start a valuation, provide your company financials and comparable companies, and the system runs a full multi-method analysis (DCF, Market Comps, OPM Backsolve) with DLOM calculation. You get a complete valuation report in minutes. Best for early-stage companies between formal appraisals. **AI + Reviewer:** For audit-ready valuations, assign a reviewer to the report. The reviewer (typically an outside appraiser, CFO, or board member) examines the inputs and methodology, leaves notes, and formally approves or requests changes. The report can then be finalized and locked, creating an immutable record with a defensible audit trail. ### How it works 1. **Start a valuation** -- Tell the assistant you need a 409A, or call `POST /api/409a/start` with your valuation date and company details. 2. **Provide inputs** -- Company financials (revenue, EBITDA, cash, projections), comparable public companies with EV/Revenue multiples, and DCF assumptions (discount rate, terminal growth rate). 3. **Compute** -- The system runs three valuation methods and weights them to arrive at enterprise value, then allocates to common equity and applies a DLOM (Discount for Lack of Marketability). 4. **Review (optional)** -- Assign a reviewer who can approve or request changes. 5. **Finalize** -- Lock the report. The resulting FMV is available for option pricing. ### Valuation methods - **Discounted Cash Flow (DCF)** -- Projects future cash flows and discounts them to present value using a risk-adjusted discount rate. - **Market Comparables** -- Uses EV/Revenue and EV/EBITDA multiples from comparable public companies to estimate enterprise value. - **OPM Backsolve** -- Uses the Option Pricing Method to backsolve from the most recent preferred stock price to implied common stock value, accounting for the preferred stock's economic rights (liquidation preferences, participation). - **DLOM** -- Applies a Discount for Lack of Marketability to reflect that private company shares cannot be freely traded. --- ## SBC Expensing (Stock-Based Compensation) For companies that need to track stock-based compensation expense -- whether for GAAP financial statements, investor reporting, or tax compliance -- Invisible computes it automatically. ### Black-Scholes valuation Each option grant's fair value is calculated using the Black-Scholes option pricing model with these inputs: - **Fair market value** -- From your most recent 409A valuation - **Exercise price** -- From the grant terms - **Expected term** -- Typically 5-7 years for employee options (simplified method) - **Risk-free rate** -- US Treasury yield matching the expected term - **Volatility** -- Based on comparable public companies - **Dividend yield** -- Typically zero for private companies ### Expense scheduling SBC expense is recognized over each grant's vesting period on a straight-line basis. The system generates monthly expense schedules that you can filter by: - **Date range** -- Any period you need (monthly close, quarterly reporting, annual audit) - **Department** -- Engineering, Sales, Product, Executive, etc. - **Individual grant** -- Drill into a specific grant's amortization ### ASC 718 disclosure At fiscal year-end, pull a complete ASC 718 disclosure package including: - Total SBC expense for the period - Grant activity rollforward (beginning balance, granted, exercised, forfeited, ending balance) - Weighted-average exercise prices and grant-date fair values - Weighted-average Black-Scholes assumptions used - Unamortized expense and remaining vesting period This gives your auditors everything they need for the stock-based compensation footnote. --- ## Reviewer Role and Workflow The reviewer workflow adds a layer of human oversight to AI-generated 409A valuations. This is important for audit defensibility and governance. ### Who can be a reviewer? Any organization member can be assigned as a reviewer. In practice, this is typically: - An outside valuation firm or independent appraiser - The company CFO or VP Finance - A board member or audit committee member ### Workflow 1. **Admin creates and computes a valuation** -- The AI runs the full multi-method analysis. 2. **Admin assigns a reviewer** -- The reviewer receives access to the full report. 3. **Reviewer examines the report** -- Reviews inputs, comparable companies, methodology weights, DCF assumptions, and the resulting FMV. 4. **Reviewer submits their decision** -- Approves the report (with optional notes) or requests changes (with notes explaining what needs to change). 5. **If changes requested** -- The admin updates inputs and re-computes. The reviewer reviews again. 6. **Admin finalizes** -- Once approved, the admin locks the report as final. No further edits are possible. ### Permissions | Action | Who can do it | |--------|--------------| | Start a valuation | Owner, Admin | | Update inputs | Owner, Admin | | Compute valuation | Owner, Admin | | Assign reviewer | Owner, Admin | | Submit review | Assigned reviewer only | | Finalize report | Owner, Admin | | View reports | All authenticated members | --- ## API Documentation Full API reference for building integrations: - **Markdown (AI-friendly):** https://api.invisible.app/docs/api - **OpenAPI 3.0 spec:** https://api.invisible.app/docs/openapi.yaml These docs are optimized for use with AI coding assistants. Feed them to Claude, Cursor, or Copilot to generate integration code. ## Pricing Invisible Cap Table is currently in early access. Contact us for pricing information. ## Getting Started Just start chatting! If you're new, the assistant will guide you through setting up your organization and loading your cap table data. If you're an investor or employee who received an invite code, sign up and enter your code to see your holdings. # Invisible Cap Table API Reference Base URL: `https://api.invisible.app` JSON naming: all request/response fields use **camelCase**. Enum values use **camelCase** (e.g., `"common"`, `"convertibleNote"`). --- ## 1. Authentication All endpoints except `/health`, `/api/chat/public`, and OAuth metadata require authentication. ### Method A: API Key Get a key by asking the chat assistant at [invisible.app](https://invisible.app). ``` Authorization: Bearer icap_YOUR_KEY ``` The API key is scoped to a single organization. No additional headers needed. ### Method B: JWT (Cognito) ``` Authorization: Bearer X-Organization-Id: ``` `X-Organization-Id` is required for all endpoints except `/api/me`, `/api/organizations`, `/api/invites/redeem`, `/api/org-invites/redeem`, `/api/chat`, and `/api/conversations`. ### Role-Based Access | Role | Read cap table | Write cap table | Manage members | |------|---------------|-----------------|----------------| | `owner` | Full | Yes | Yes | | `admin` | Full | Yes | Yes | | `member` | Full | Yes | No | | `viewer` | Full (if `canViewFullCapTable=true`) or own holdings only | No | No | | `employee` | Own holdings only | No | No | Write endpoints (`POST`, `PUT`, `DELETE` on cap table data) return `403` for `viewer` and `employee` roles. **Visibility modifiers** for restricted viewers (viewer without full cap table, employee): - **Manager hierarchy**: If the user's linked stakeholder has reports (via `manager_id`), they see the full subtree of reports' equity data. - **Department access**: Admins can grant users view access to all equity data in specific departments via `department_access`. - The user sees the union of: own holdings + report tree + department access. --- ## 2. Cap Table (Read) ### GET /api/cap-table Full cap table with all stakeholders, summary, security classes, and investor groups. **Auth:** Required. Restricted viewers see only their own holdings. ```bash curl -s https://api.invisible.app/api/cap-table \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "stakeholders": [ { "id": "a1b2c3d4-0001-4000-8000-000000000001", "name": "Sarah Chen", "type": "individual", "commonShares": 4000000, "preferredShares": 0, "preferredSeriesDetail": [], "optionShares": 0, "fullyDilutedShares": 4000000, "ownershipPct": 40.0 }, { "id": "a1b2c3d4-0001-4000-8000-000000000002", "name": "Sequoia Capital", "type": "entity", "commonShares": 0, "preferredShares": 2000000, "preferredSeriesDetail": [ { "series": "Series A Preferred", "shares": 2000000, "asConvertedShares": 2000000 } ], "optionShares": 0, "fullyDilutedShares": 2000000, "ownershipPct": 20.0 } ], "summary": { "totalCommon": 6000000, "totalPreferred": 2000000, "totalOptionsOutstanding": 500000, "totalFullyDiluted": 10000000, "optionPoolAuthorized": 1000000, "optionPoolAvailable": 500000 }, "securityClasses": [ { "id": "b2c3d4e5-0001-4000-8000-000000000001", "name": "Common Stock", "type": "common", "authorizedShares": 8000000, "outstandingShares": 6000000, "originalIssuePrice": null, "liquidationPreference": null, "conversionRatio": 1.0, "isParticipating": false, "participationCap": null, "seniorityRank": null }, { "id": "b2c3d4e5-0001-4000-8000-000000000002", "name": "Series A Preferred", "type": "preferred", "authorizedShares": 3000000, "outstandingShares": 2000000, "originalIssuePrice": 1.50, "liquidationPreference": 1.0, "conversionRatio": 1.0, "isParticipating": false, "participationCap": null, "seniorityRank": 1 } ], "investorGroups": [ { "id": "c3d4e5f6-0001-4000-8000-000000000001", "name": "Series A Investors", "totalShares": 2000000, "ownershipPct": 20.0, "memberIds": ["a1b2c3d4-0001-4000-8000-000000000002"] } ] } ``` --- ### GET /api/stakeholders List all stakeholders. Supports search. **Auth:** Required. Restricted viewers see only themselves. **Query params:** | Param | Type | Description | |-------|------|-------------| | `search` | string | Filter by name (partial match) | ```bash curl -s "https://api.invisible.app/api/stakeholders?search=chen" \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "stakeholders": [ { "id": "a1b2c3d4-0001-4000-8000-000000000001", "name": "Sarah Chen", "type": "individual", "email": "sarah@acme.com", "jobTitle": "CEO", "department": "Executive", "managerId": null, "managerName": null, "isActive": true } ] } ``` --- ### GET /api/stakeholders/{id} Detailed view of a single stakeholder including holdings, transactions, and option grants. **Auth:** Required. Restricted viewers can only access their own linked stakeholder. ```bash curl -s https://api.invisible.app/api/stakeholders/a1b2c3d4-0001-4000-8000-000000000001 \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "stakeholder": { "id": "a1b2c3d4-0001-4000-8000-000000000001", "organizationId": "d4e5f6a7-0001-4000-8000-000000000001", "name": "Sarah Chen", "type": "individual", "email": "sarah@acme.com", "jobTitle": "CEO", "department": "Executive", "employeeId": "EMP-001", "userId": null, "isActive": true, "createdAt": "2024-01-15T00:00:00Z", "updatedAt": "2024-01-15T00:00:00Z" }, "holdings": [ { "securityClass": "Common Stock", "shares": 4000000, "pctOwnership": 40.0 } ], "transactions": [ { "id": "e5f6a7b8-0001-4000-8000-000000000001", "securityId": "CS-001", "type": "issuance", "shares": 4000000, "pricePerShare": 0.001, "date": "2024-01-15T00:00:00Z", "notes": "Founder shares" } ], "optionGrants": [] } ``` --- ### GET /api/security-classes List all security classes for the organization. **Auth:** Required. ```bash curl -s https://api.invisible.app/api/security-classes \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "classes": [ { "id": "b2c3d4e5-0001-4000-8000-000000000001", "name": "Common Stock", "type": "common", "authorizedShares": 8000000, "outstandingShares": 6000000, "originalIssuePrice": null, "liquidationPreference": null, "conversionRatio": 1.0, "isParticipating": false, "participationCap": null, "seniorityRank": null } ] } ``` --- ### GET /api/equity-plans List all equity incentive plans. **Auth:** Required. ```bash curl -s https://api.invisible.app/api/equity-plans \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "plans": [ { "id": "f6a7b8c9-0001-4000-8000-000000000001", "organizationId": "d4e5f6a7-0001-4000-8000-000000000001", "name": "2024 Equity Incentive Plan", "year": 2024, "authorizedShares": 1000000, "createdAt": "2024-01-15T00:00:00Z" } ] } ``` --- ## 3. Option Grants ### GET /api/option-grants List option grants with optional filters. **Auth:** Required. Restricted viewers see only their own grants. **Query params:** | Param | Type | Description | |-------|------|-------------| | `stakeholderId` | uuid | Filter by stakeholder | | `department` | string | Filter by department | | `status` | string | Comma-separated. Values: `proposed`, `pendingApproval`, `approved`, `active`, `fullyVested`, `exercised`, `partiallyExercised`, `cancelled`, `expired` | | `planName` | string | Filter by equity plan name | | `asOfDate` | string | Calculate vesting as of this date (`YYYY-MM-DD`) | ```bash curl -s "https://api.invisible.app/api/option-grants?status=active,fullyVested&department=Engineering" \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "grants": [ { "id": "11111111-0001-4000-8000-000000000001", "employeeName": "James Park", "jobTitle": "Senior Engineer", "department": "Engineering", "grantNumber": "OPT-2024-001", "optionType": "iso", "grantDate": "2024-03-01T00:00:00Z", "vestingStartDate": "2024-03-01T00:00:00Z", "exercisePrice": 0.50, "sharesGranted": 50000, "sharesVested": 12500, "sharesUnvested": 37500, "sharesExercised": 0, "sharesExercisable": 12500, "expirationDate": "2034-03-01T00:00:00Z", "status": "active", "category": "newHire", "notes": null, "planName": "2024 Equity Incentive Plan" } ] } ``` --- ### POST /api/option-grants Create an option grant. Uses the **preview/confirm pattern**: first call with `confirm: false` to see impact, then call with `confirm: true` to commit. **Auth:** Required. `owner`, `admin`, or `member` role. **Enum values:** - `optionType`: `iso`, `nqso`, `rsu` - `status`: `proposed`, `pendingApproval`, `approved`, `active`, `fullyVested`, `exercised`, `partiallyExercised`, `cancelled`, `expired` - `category`: `newHire`, `promotion`, `retention`, `performance`, `refresh`, `advisory`, `other` #### Step 1: Preview (confirm=false) ```bash curl -s -X POST https://api.invisible.app/api/option-grants \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000003", "equityPlanId": "f6a7b8c9-0001-4000-8000-000000000001", "optionType": "iso", "sharesGranted": 50000, "exercisePrice": 0.50, "grantDate": "2024-03-01", "vestingStartDate": "2024-03-01", "expirationDate": "2034-03-01", "vestingScheduleId": "22222222-0001-4000-8000-000000000001", "status": "active", "category": "newHire", "grantNumber": "OPT-2024-001", "notes": "New hire grant for Senior Engineer", "confirm": false }' ``` **Preview response:** ```json { "preview": { "grantDetail": { "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000003", "equityPlanId": "f6a7b8c9-0001-4000-8000-000000000001", "optionType": "iso", "sharesGranted": 50000, "exercisePrice": 0.50, "grantDate": "2024-03-01", "vestingStartDate": "2024-03-01", "expirationDate": "2034-03-01", "vestingScheduleId": "22222222-0001-4000-8000-000000000001", "status": "active", "category": "newHire", "grantNumber": "OPT-2024-001", "notes": "New hire grant for Senior Engineer", "confirm": false }, "poolImpact": { "availableBefore": 500000, "availableAfter": 450000, "pctPoolUsed": 55.0 }, "validationWarnings": [] } } ``` #### Step 2: Commit (confirm=true) Same request body with `"confirm": true`. ```bash curl -s -X POST https://api.invisible.app/api/option-grants \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000003", "equityPlanId": "f6a7b8c9-0001-4000-8000-000000000001", "optionType": "iso", "sharesGranted": 50000, "exercisePrice": 0.50, "grantDate": "2024-03-01", "vestingStartDate": "2024-03-01", "expirationDate": "2034-03-01", "vestingScheduleId": "22222222-0001-4000-8000-000000000001", "status": "active", "category": "newHire", "grantNumber": "OPT-2024-001", "confirm": true }' ``` **Commit response:** ```json { "grantId": "11111111-0001-4000-8000-000000000001", "preview": { "grantDetail": { "..." : "same as above" }, "poolImpact": { "availableBefore": 500000, "availableAfter": 450000, "pctPoolUsed": 55.0 }, "validationWarnings": [] } } ``` --- ### PUT /api/option-grants Update an existing option grant. Only provided fields are modified. **Auth:** Required. `owner`, `admin`, or `member` role. ```bash curl -s -X PUT https://api.invisible.app/api/option-grants \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "grantId": "11111111-0001-4000-8000-000000000001", "sharesGranted": 60000, "exercisePrice": 0.75, "category": "promotion", "notes": "Adjusted after promotion to Staff Engineer", "status": "active" }' ``` **Response:** ```json { "updated": true } ``` Returns `404` if grant not found. --- ### DELETE /api/option-grants/{id} Delete an option grant. **Auth:** Required. `owner`, `admin`, or `member` role. ```bash curl -s -X DELETE https://api.invisible.app/api/option-grants/11111111-0001-4000-8000-000000000001 \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "deleted": true } ``` Returns `404` if grant not found. --- ### POST /api/option-grants/exercise Exercise vested options. Uses **preview/confirm pattern**. **Auth:** Required. `owner`, `admin`, or `member` role. #### Preview ```bash curl -s -X POST https://api.invisible.app/api/option-grants/exercise \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "grantId": "11111111-0001-4000-8000-000000000001", "sharesToExercise": 10000, "exerciseDate": "2025-06-15", "notes": "Partial exercise", "confirm": false }' ``` **Preview response:** ```json { "preview": { "grantId": "11111111-0001-4000-8000-000000000001", "sharesGranted": 50000, "sharesVested": 12500, "sharesPreviouslyExercised": 0, "sharesExercisable": 12500, "sharesToExercise": 10000, "sharesRemainingAfter": 2500, "newStatus": "partiallyExercised", "validationWarnings": [] } } ``` #### Commit Same body with `"confirm": true`. **Commit response:** ```json { "exerciseId": "33333333-0001-4000-8000-000000000001", "preview": { "...": "same as above" } } ``` --- ### POST /api/grant-status Batch-update the status of one or more grants. Uses **preview/confirm pattern**. **Auth:** Required. `owner`, `admin`, or `member` role. #### Preview ```bash curl -s -X POST https://api.invisible.app/api/grant-status \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "grantIds": [ "11111111-0001-4000-8000-000000000001", "11111111-0001-4000-8000-000000000002" ], "newStatus": "approved", "notes": "Board approved Q1 grants", "confirm": false }' ``` **Preview response:** ```json { "grantsAffected": 2, "confirmRequired": true } ``` #### Commit ```bash curl -s -X POST https://api.invisible.app/api/grant-status \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "grantIds": [ "11111111-0001-4000-8000-000000000001", "11111111-0001-4000-8000-000000000002" ], "newStatus": "approved", "notes": "Board approved Q1 grants", "confirm": true }' ``` **Commit response:** ```json { "success": true, "grantsAffected": 2 } ``` --- ### GET /api/vesting-schedules List all vesting schedule templates. **Auth:** Required. ```bash curl -s https://api.invisible.app/api/vesting-schedules \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "schedules": [ { "id": "22222222-0001-4000-8000-000000000001", "name": "Standard 4-year with 1-year cliff", "totalMonths": 48, "cliffMonths": 12, "frequency": "monthly", "createdAt": "2024-01-15T00:00:00Z" } ] } ``` --- ### POST /api/vesting-schedules Create a new vesting schedule template. **Auth:** Required. `owner`, `admin`, or `member` role. **Enum values for `frequency`:** `monthly`, `quarterly`, `annually` ```bash curl -s -X POST https://api.invisible.app/api/vesting-schedules \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "3-year quarterly with 6-month cliff", "totalMonths": 36, "cliffMonths": 6, "frequency": "quarterly" }' ``` **Response:** ```json { "vestingScheduleId": "22222222-0001-4000-8000-000000000002" } ``` --- ## 4. Transactions ### GET /api/transactions Transaction history with optional filters. **Auth:** Required. **Query params:** | Param | Type | Description | |-------|------|-------------| | `stakeholderId` | uuid | Filter by stakeholder | | `securityClassId` | uuid | Filter by security class | | `type` | string | One of: `issuance`, `grant`, `exercise`, `transfer`, `cancellation`, `repurchase`, `conversion` | | `startDate` | string | Start date (`YYYY-MM-DD`) | | `endDate` | string | End date (`YYYY-MM-DD`) | ```bash curl -s "https://api.invisible.app/api/transactions?type=issuance&startDate=2024-01-01&endDate=2024-12-31" \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "transactions": [ { "id": "e5f6a7b8-0001-4000-8000-000000000001", "securityId": "CS-001", "type": "issuance", "shares": 4000000, "pricePerShare": 0.001, "date": "2024-01-15T00:00:00Z", "notes": "Founder shares" } ] } ``` --- ### POST /api/transactions Record a transaction. Uses **preview/confirm pattern**. **Auth:** Required. `owner`, `admin`, or `member` role. **Enum values for `type`:** `issuance`, `grant`, `exercise`, `transfer`, `cancellation`, `repurchase`, `conversion` #### Preview ```bash curl -s -X POST https://api.invisible.app/api/transactions \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "securityId": "SA-001", "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000002", "securityClassId": "b2c3d4e5-0001-4000-8000-000000000002", "type": "issuance", "shares": 2000000, "pricePerShare": 1.50, "transactionDate": "2024-06-01", "notes": "Series A investment", "confirm": false }' ``` **Preview response:** ```json { "preview": { "transactionDetail": { "securityId": "SA-001", "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000002", "securityClassId": "b2c3d4e5-0001-4000-8000-000000000002", "type": "issuance", "shares": 2000000, "pricePerShare": 1.50, "transactionDate": "2024-06-01", "notes": "Series A investment", "confirm": false }, "validationWarnings": [], "impact": { "sharesBefore": 0, "sharesAfter": 2000000, "ownershipPctChange": 20.0 } } } ``` #### Commit Same body with `"confirm": true`. **Commit response:** ```json { "transactionId": "e5f6a7b8-0001-4000-8000-000000000002", "preview": { "...": "same as above" } } ``` --- ## 5. Organization Management ### GET /api/me Current user profile with all org memberships and linked stakeholders. **Auth:** Required. No `X-Organization-Id` needed. ```bash curl -s https://api.invisible.app/api/me \ -H "Authorization: Bearer " ``` **Response:** ```json { "userId": "44444444-0001-4000-8000-000000000001", "email": "sarah@acme.com", "name": "Sarah Chen", "organizations": [ { "organizationId": "d4e5f6a7-0001-4000-8000-000000000001", "organizationName": "Acme Inc", "role": "owner", "canViewFullCapTable": true } ], "linkedStakeholders": [ { "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000001", "organizationId": "d4e5f6a7-0001-4000-8000-000000000001", "organizationName": "Acme Inc", "name": "Sarah Chen", "type": "individual" } ] } ``` --- ### POST /api/organizations Create a new organization. The creating user becomes `owner`. **Auth:** Required (JWT). No `X-Organization-Id` needed. ```bash curl -s -X POST https://api.invisible.app/api/organizations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Inc", "slug": "acme", "domain": "acme.com" }' ``` **Response:** ```json { "organizationId": "d4e5f6a7-0001-4000-8000-000000000001" } ``` --- ### GET /api/organizations/{id}/members List all members of an organization. **Auth:** Required. `owner` or `admin` role. ```bash curl -s https://api.invisible.app/api/organizations/d4e5f6a7-0001-4000-8000-000000000001/members \ -H "Authorization: Bearer " \ -H "X-Organization-Id: d4e5f6a7-0001-4000-8000-000000000001" ``` **Response:** ```json { "members": [ { "id": "55555555-0001-4000-8000-000000000001", "organizationId": "d4e5f6a7-0001-4000-8000-000000000001", "userId": "44444444-0001-4000-8000-000000000001", "role": "owner", "canViewFullCapTable": true, "createdAt": "2024-01-15T00:00:00Z" } ] } ``` --- ### POST /api/organizations/{id}/members Invite a user to the organization. If the user already has an account, they are added immediately. Otherwise, an invite code is generated. **Auth:** Required. `owner` or `admin` role. **Enum values for `role`:** `owner`, `admin`, `member`, `viewer`, `employee` ```bash curl -s -X POST https://api.invisible.app/api/organizations/d4e5f6a7-0001-4000-8000-000000000001/members \ -H "Authorization: Bearer " \ -H "X-Organization-Id: d4e5f6a7-0001-4000-8000-000000000001" \ -H "Content-Type: application/json" \ -d '{ "email": "james@acme.com", "role": "member", "expiresInDays": 7 }' ``` **Response (user exists):** ```json { "added": true, "message": "User james@acme.com added to organization as member" } ``` **Response (user must sign up):** ```json { "added": false, "inviteCode": "abc123def456", "message": "Invite created for james@acme.com (user must sign up first)" } ``` --- ### PUT /api/organizations/{id}/members/{userId} Update a member's role or cap table visibility. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X PUT https://api.invisible.app/api/organizations/d4e5f6a7-0001-4000-8000-000000000001/members/44444444-0001-4000-8000-000000000002 \ -H "Authorization: Bearer " \ -H "X-Organization-Id: d4e5f6a7-0001-4000-8000-000000000001" \ -H "Content-Type: application/json" \ -d '{ "role": "admin", "canViewFullCapTable": true }' ``` **Response:** ```json { "updated": true } ``` --- ### POST /api/org-invites/redeem Redeem an organization invite code. **Auth:** Required (JWT). No `X-Organization-Id` needed. ```bash curl -s -X POST https://api.invisible.app/api/org-invites/redeem \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "inviteCode": "abc123def456" }' ``` **Response:** ```json { "redeemed": true } ``` --- ### POST /api/organizations/{id}/invite Create a stakeholder invite that links a user account to a stakeholder record (e.g., so an employee can view their own holdings). **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X POST https://api.invisible.app/api/organizations/d4e5f6a7-0001-4000-8000-000000000001/invite \ -H "Authorization: Bearer " \ -H "X-Organization-Id: d4e5f6a7-0001-4000-8000-000000000001" \ -H "Content-Type: application/json" \ -d '{ "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000003", "email": "james@acme.com", "expiresInDays": 7 }' ``` **Response:** ```json { "inviteCode": "xyz789abc012", "expiresInDays": 7 } ``` --- ### POST /api/invites/redeem Redeem a stakeholder invite code (links the authenticated user to the stakeholder). **Auth:** Required (JWT). No `X-Organization-Id` needed. ```bash curl -s -X POST https://api.invisible.app/api/invites/redeem \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "inviteCode": "xyz789abc012" }' ``` **Response:** ```json { "redeemed": true } ``` --- ## 6. Bulk Operations All bulk endpoints require `owner`, `admin`, or `member` role. ### POST /api/bulk/stakeholders Create multiple stakeholders in one call. **Auth:** Required. `owner`, `admin`, or `member` role. **Enum values for `type`:** `individual`, `entity`, `trust`, `fund`, `spv` ```bash curl -s -X POST https://api.invisible.app/api/bulk/stakeholders \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "stakeholders": [ { "name": "James Park", "type": "individual", "email": "james@acme.com", "jobTitle": "Senior Engineer", "department": "Engineering", "employeeId": "EMP-003" }, { "name": "Acme Ventures LLC", "type": "entity", "email": "legal@acmeventures.com" } ] }' ``` **Response:** ```json { "results": [ { "name": "James Park", "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000003", "error": null }, { "name": "Acme Ventures LLC", "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000004", "error": null } ], "created": 2, "failed": 0 } ``` --- ### POST /api/bulk/transactions Record multiple transactions. Each transaction is committed individually (no preview step). Failures do not roll back successes. **Auth:** Required. `owner`, `admin`, or `member` role. ```bash curl -s -X POST https://api.invisible.app/api/bulk/transactions \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "transactions": [ { "securityId": "CS-002", "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000003", "securityClassId": "b2c3d4e5-0001-4000-8000-000000000001", "type": "issuance", "shares": 100000, "pricePerShare": 0.50, "transactionDate": "2024-03-01", "notes": "Early exercise of options", "confirm": true }, { "securityId": "SA-002", "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000004", "securityClassId": "b2c3d4e5-0001-4000-8000-000000000002", "type": "issuance", "shares": 500000, "pricePerShare": 1.50, "transactionDate": "2024-06-01", "notes": "Series A participation", "confirm": true } ] }' ``` **Response:** ```json { "results": [ { "securityId": "CS-002", "transactionId": "e5f6a7b8-0001-4000-8000-000000000003", "error": null }, { "securityId": "SA-002", "transactionId": "e5f6a7b8-0001-4000-8000-000000000004", "error": null } ], "created": 2, "failed": 0 } ``` --- ### POST /api/bulk/option-grants Create multiple option grants. Each grant is committed individually. Failures do not roll back successes. **Auth:** Required. `owner`, `admin`, or `member` role. ```bash curl -s -X POST https://api.invisible.app/api/bulk/option-grants \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "grants": [ { "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000003", "equityPlanId": "f6a7b8c9-0001-4000-8000-000000000001", "optionType": "iso", "sharesGranted": 50000, "exercisePrice": 0.50, "grantDate": "2024-03-01", "vestingStartDate": "2024-03-01", "expirationDate": "2034-03-01", "vestingScheduleId": "22222222-0001-4000-8000-000000000001", "status": "active", "category": "newHire", "confirm": true }, { "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000005", "equityPlanId": "f6a7b8c9-0001-4000-8000-000000000001", "optionType": "nqso", "sharesGranted": 25000, "exercisePrice": 0.50, "grantDate": "2024-04-01", "vestingStartDate": "2024-04-01", "expirationDate": "2034-04-01", "status": "active", "category": "advisory", "confirm": true } ] }' ``` **Response:** ```json { "results": [ { "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000003", "grantId": "11111111-0001-4000-8000-000000000001", "error": null }, { "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000005", "grantId": "11111111-0001-4000-8000-000000000002", "error": null } ], "created": 2, "failed": 0 } ``` --- ## 7. Additional Write Endpoints ### POST /api/stakeholders Create a single stakeholder. **Auth:** Required. `owner`, `admin`, or `member` role. ```bash curl -s -X POST https://api.invisible.app/api/stakeholders \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "James Park", "type": "individual", "email": "james@acme.com", "jobTitle": "Senior Engineer", "department": "Engineering", "employeeId": "EMP-003", "managerId": "a1b2c3d4-0001-4000-8000-000000000001" }' ``` **Response:** ```json { "stakeholderId": "a1b2c3d4-0001-4000-8000-000000000003" } ``` --- ### POST /api/security-classes Create a new security class. **Auth:** Required. `owner`, `admin`, or `member` role. **Enum values for `type`:** `common`, `preferred`, `option`, `warrant`, `safe`, `convertibleNote` ```bash curl -s -X POST https://api.invisible.app/api/security-classes \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Series B Preferred", "type": "preferred", "originalIssuePrice": 5.00, "liquidationPreference": 1.0, "conversionRatio": 1.0, "isParticipating": false, "seniorityRank": 2, "authorizedShares": 5000000 }' ``` **Response:** ```json { "securityClassId": "b2c3d4e5-0001-4000-8000-000000000003" } ``` --- ### PUT /api/security-classes Update a security class. **Auth:** Required. `owner`, `admin`, or `member` role. ```bash curl -s -X PUT https://api.invisible.app/api/security-classes \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "securityClassId": "b2c3d4e5-0001-4000-8000-000000000002", "authorizedShares": 4000000, "conversionRatio": 1.2, "notes": "Updated after anti-dilution adjustment" }' ``` **Response:** ```json { "updated": true } ``` --- ### POST /api/equity-plans Create a new equity incentive plan. **Auth:** Required. `owner`, `admin`, or `member` role. ```bash curl -s -X POST https://api.invisible.app/api/equity-plans \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "2025 Equity Incentive Plan", "year": 2025, "authorizedShares": 1500000 }' ``` **Response:** ```json { "equityPlanId": "f6a7b8c9-0001-4000-8000-000000000002" } ``` --- ### PUT /api/equity-plans Update an equity plan. **Auth:** Required. `owner`, `admin`, or `member` role. ```bash curl -s -X PUT https://api.invisible.app/api/equity-plans \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "equityPlanId": "f6a7b8c9-0001-4000-8000-000000000001", "authorizedShares": 1200000 }' ``` **Response:** ```json { "updated": true } ``` --- ### POST /api/investor-groups Create or update an investor group. **Auth:** Required. `owner`, `admin`, or `member` role. ```bash curl -s -X POST https://api.invisible.app/api/investor-groups \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Series A Investors", "stakeholderIds": [ "a1b2c3d4-0001-4000-8000-000000000002", "a1b2c3d4-0001-4000-8000-000000000004" ] }' ``` To update an existing group, include `groupId`: ```bash curl -s -X POST https://api.invisible.app/api/investor-groups \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "groupId": "c3d4e5f6-0001-4000-8000-000000000001", "name": "Series A Investors", "stakeholderIds": [ "a1b2c3d4-0001-4000-8000-000000000002", "a1b2c3d4-0001-4000-8000-000000000004", "a1b2c3d4-0001-4000-8000-000000000006" ] }' ``` **Response:** ```json { "groupId": "c3d4e5f6-0001-4000-8000-000000000001" } ``` --- ## 8. MCP Integration The Invisible Cap Table exposes an MCP (Model Context Protocol) server for AI assistant integrations. **Endpoint:** `https://mcp.invisible.app/mcp` **Transport:** Streamable HTTP (stateless) **Auth:** OAuth 2.0 with PKCE. The authorization server metadata is at `https://api.invisible.app/.well-known/oauth-authorization-server`. MCP clients (Claude Desktop, Cursor, etc.) can discover the server and authenticate automatically using the standard MCP OAuth flow. The server exposes the same cap table read/write operations as the REST API as MCP tools. --- ## 9. 409A Valuations ### POST /api/409a/start Start a new 409A valuation. Creates a draft report with initial inputs. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X POST https://api.invisible.app/api/409a/start \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "valuationDate": "2026-03-31", "companyDescription": "Series B SaaS company, $8M ARR, 45% YoY growth", "industry": "Enterprise Software / SaaS", "financials": { "revenue": 8000000, "revenueGrowthRate": 0.45, "ebitda": -1200000, "cashBalance": 12000000, "totalDebt": 0, "projectedRevenue": [12000000, 18000000, 26000000, 35000000, 42000000] }, "dcfAssumptions": { "discountRate": 0.30, "terminalGrowthRate": 0.03, "projectionYears": 5 }, "comparableCompanies": [ { "name": "Comparable A", "evRevenue": 12.5, "evEbitda": null }, { "name": "Comparable B", "evRevenue": 9.8, "evEbitda": 45.0 }, { "name": "Comparable C", "evRevenue": 15.2, "evEbitda": null } ], "methodologyWeights": { "dcf": 0.30, "marketComps": 0.40, "opmBacksolve": 0.30 } }' ``` **Response:** ```json { "reportId": "99999999-0001-4000-8000-000000000001" } ``` --- ### GET /api/409a/reports List all 409A valuation reports for the organization. **Auth:** Required. ```bash curl -s https://api.invisible.app/api/409a/reports \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "reports": [ { "id": "99999999-0001-4000-8000-000000000001", "valuationDate": "2026-03-31", "status": "draft", "fairMarketValue": null, "reviewerUserId": null, "createdAt": "2026-03-31T14:00:00Z", "finalizedAt": null } ] } ``` --- ### GET /api/409a/reports/{id} Full report detail including inputs, calculated values, equity allocation, and review status. **Auth:** Required. ```bash curl -s https://api.invisible.app/api/409a/reports/99999999-0001-4000-8000-000000000001 \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "id": "99999999-0001-4000-8000-000000000001", "valuationDate": "2026-03-31", "status": "computed", "inputs": { "companyDescription": "Series B SaaS company, $8M ARR, 45% YoY growth", "industry": "Enterprise Software / SaaS", "financials": { "revenue": 8000000, "revenueGrowthRate": 0.45, "ebitda": -1200000 }, "dcfAssumptions": { "discountRate": 0.30, "terminalGrowthRate": 0.03, "projectionYears": 5 }, "comparableCompanies": [ "..." ], "methodologyWeights": { "dcf": 0.30, "marketComps": 0.40, "opmBacksolve": 0.30 } }, "calculations": { "dcfValue": 85000000, "marketCompsValue": 96000000, "opmBacksolveValue": 91000000, "weightedEnterpriseValue": 91500000, "dlomDiscount": 0.25, "fairMarketValuePerShare": 1.85 }, "allocation": { "enterpriseValue": 91500000, "commonEquityValue": 18500000, "commonSharesOutstanding": 10000000, "preDlomPerShare": 1.85, "dlom": 0.25, "postDlomPerShare": 1.39 }, "reviewerUserId": null, "reviewNotes": null, "reviewApproved": null, "createdAt": "2026-03-31T14:00:00Z", "finalizedAt": null } ``` --- ### PUT /api/409a/reports/{id}/inputs Update the inputs on a draft or computed report (financials, comparable companies, assumptions). Cannot update a finalized report. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X PUT https://api.invisible.app/api/409a/reports/99999999-0001-4000-8000-000000000001/inputs \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "financials": { "revenue": 8500000, "revenueGrowthRate": 0.48, "ebitda": -800000, "cashBalance": 11000000, "totalDebt": 0, "projectedRevenue": [13000000, 19500000, 28000000, 37000000, 44000000] }, "comparableCompanies": [ { "name": "Comparable A", "evRevenue": 13.0, "evEbitda": null }, { "name": "Comparable B", "evRevenue": 10.2, "evEbitda": 42.0 }, { "name": "Comparable C", "evRevenue": 14.8, "evEbitda": null }, { "name": "Comparable D", "evRevenue": 11.5, "evEbitda": 50.0 } ] }' ``` **Response:** ```json { "updated": true } ``` Returns `400` if the report is finalized. --- ### POST /api/409a/reports/{id}/compute Run the full valuation computation: DCF, Market Comps, OPM Backsolve, and DLOM calculation. Updates the report with calculated values. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X POST https://api.invisible.app/api/409a/reports/99999999-0001-4000-8000-000000000001/compute \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "computed": true, "fairMarketValuePerShare": 1.39, "enterpriseValue": 91500000, "methodResults": { "dcf": 85000000, "marketComps": 96000000, "opmBacksolve": 91000000 }, "dlomDiscount": 0.25 } ``` --- ### POST /api/409a/reports/{id}/assign-reviewer Assign a reviewer to a 409A report. The reviewer must be a member of the organization. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X POST https://api.invisible.app/api/409a/reports/99999999-0001-4000-8000-000000000001/assign-reviewer \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "reviewerUserId": "44444444-0001-4000-8000-000000000002" }' ``` **Response:** ```json { "assigned": true } ``` --- ### POST /api/409a/reports/{id}/review Submit a review for a 409A report. Only the assigned reviewer can call this endpoint. **Auth:** Required. Must be the assigned reviewer. ```bash curl -s -X POST https://api.invisible.app/api/409a/reports/99999999-0001-4000-8000-000000000001/review \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "notes": "Methodology and assumptions look reasonable. Comparable set is appropriate for this stage and industry. DLOM within expected range.", "approve": true }' ``` **Response:** ```json { "reviewed": true, "approved": true } ``` Returns `403` if the caller is not the assigned reviewer. --- ### POST /api/409a/reports/{id}/finalize Lock the report as final. Once finalized, no further edits are allowed. The fair market value is recorded for use in option pricing. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X POST https://api.invisible.app/api/409a/reports/99999999-0001-4000-8000-000000000001/finalize \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "finalized": true, "fairMarketValuePerShare": 1.39, "valuationDate": "2026-03-31" } ``` Returns `400` if the report has not been computed yet. --- ## 10. SBC Expensing ### POST /api/sbc/valuations Record a 409A valuation with Black-Scholes assumptions for SBC expense calculations. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X POST https://api.invisible.app/api/sbc/valuations \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "valuationDate": "2026-03-31", "fairMarketValue": 1.39, "expectedTermYears": 6.25, "riskFreeRate": 0.042, "volatility": 0.55, "dividendYield": 0.0, "notes": "Based on Q1 2026 409A valuation, volatility from public SaaS peer group" }' ``` **Response:** ```json { "sbcValuationId": "aaaaaaaa-0001-4000-8000-000000000001" } ``` --- ### GET /api/sbc/valuations List all SBC valuations (409A snapshots with Black-Scholes assumptions). **Auth:** Required. ```bash curl -s https://api.invisible.app/api/sbc/valuations \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "valuations": [ { "id": "aaaaaaaa-0001-4000-8000-000000000001", "valuationDate": "2026-03-31", "fairMarketValue": 1.39, "expectedTermYears": 6.25, "riskFreeRate": 0.042, "volatility": 0.55, "dividendYield": 0.0, "notes": "Based on Q1 2026 409A valuation", "createdAt": "2026-03-31T15:00:00Z" } ] } ``` --- ### POST /api/sbc/compute Compute Black-Scholes fair values and expense schedules for all active option grants, using the most recent SBC valuation assumptions. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X POST https://api.invisible.app/api/sbc/compute \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "computed": true, "grantsProcessed": 12, "totalFairValue": 485000.00, "totalUnamortizedExpense": 312000.00, "summary": { "iso": { "grants": 8, "fairValue": 350000.00 }, "nqso": { "grants": 4, "fairValue": 135000.00 } } } ``` --- ### GET /api/sbc/expense-schedule Monthly SBC expense schedule with optional filters. **Auth:** Required. **Query params:** | Param | Type | Description | |-------|------|-------------| | `startDate` | string | Start date (`YYYY-MM-DD`) | | `endDate` | string | End date (`YYYY-MM-DD`) | | `department` | string | Filter by department | | `grantId` | uuid | Filter by specific grant | ```bash curl -s "https://api.invisible.app/api/sbc/expense-schedule?startDate=2026-01-01&endDate=2026-12-31&department=Engineering" \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "schedule": [ { "month": "2026-01", "totalExpense": 12500.00, "byDepartment": { "Engineering": 8200.00, "Product": 2800.00, "Sales": 1500.00 }, "byGrantType": { "iso": 9000.00, "nqso": 3500.00 } }, { "month": "2026-02", "totalExpense": 13100.00, "byDepartment": { "Engineering": 8600.00, "Product": 2900.00, "Sales": 1600.00 }, "byGrantType": { "iso": 9400.00, "nqso": 3700.00 } } ], "totalForPeriod": 155000.00 } ``` --- ### GET /api/sbc/disclosure ASC 718 disclosure data for a fiscal year. Returns the information needed for stock-based compensation footnotes in financial statements. **Auth:** Required. **Query params:** | Param | Type | Description | |-------|------|-------------| | `fiscalYearStart` | string | Fiscal year start date (`YYYY-MM-DD`) | | `fiscalYearEnd` | string | Fiscal year end date (`YYYY-MM-DD`) | ```bash curl -s "https://api.invisible.app/api/sbc/disclosure?fiscalYearStart=2025-01-01&fiscalYearEnd=2025-12-31" \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "fiscalYear": { "start": "2025-01-01", "end": "2025-12-31" }, "totalSbcExpense": 185000.00, "grantActivity": { "outstandingBeginning": { "shares": 450000, "weightedAvgExercisePrice": 0.65 }, "granted": { "shares": 120000, "weightedAvgExercisePrice": 1.39 }, "exercised": { "shares": 30000, "weightedAvgExercisePrice": 0.50 }, "forfeited": { "shares": 15000, "weightedAvgExercisePrice": 0.75 }, "outstandingEnd": { "shares": 525000, "weightedAvgExercisePrice": 0.82 }, "exercisableEnd": { "shares": 210000, "weightedAvgExercisePrice": 0.60 } }, "weightedAvgAssumptions": { "expectedTermYears": 6.25, "riskFreeRate": 0.042, "volatility": 0.55, "dividendYield": 0.0 }, "weightedAvgGrantDateFairValue": 0.92, "unamortizedExpense": 312000.00, "weightedAvgRemainingVestingYears": 2.8 } ``` --- ## Visibility & Org Hierarchy These endpoints manage manager relationships and department-based visibility. All require `owner` or `admin` role. ### PUT /api/stakeholders/{id}/manager Set or clear a stakeholder's reporting manager. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X PUT https://api.invisible.app/api/stakeholders/a1b2c3d4-0001-4000-8000-000000000003/manager \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "managerId": "a1b2c3d4-0001-4000-8000-000000000001" }' ``` Pass `"managerId": null` to clear the manager. Returns `400` if the assignment would create a circular reference. **Response:** ```json { "updated": true } ``` --- ### POST /api/stakeholders/bulk-set-managers Set manager relationships for multiple stakeholders at once. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X POST https://api.invisible.app/api/stakeholders/bulk-set-managers \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "assignments": [ { "stakeholderId": "...", "managerId": "..." }, { "stakeholderId": "...", "managerId": "..." } ] }' ``` **Response:** ```json { "results": [ { "stakeholderId": "...", "success": true, "error": null }, { "stakeholderId": "...", "success": false, "error": "Would create circular reference" } ], "updated": 1, "failed": 1 } ``` --- ### POST /api/department-access Grant a user view access to all equity data in specified departments. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X POST https://api.invisible.app/api/department-access \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "userId": "c3d4e5f6-0001-4000-8000-000000000001", "departments": ["Sales", "Marketing"] }' ``` **Response:** ```json { "granted": 2 } ``` --- ### POST /api/department-access/revoke Revoke department-based view access. **Auth:** Required. `owner` or `admin` role. ```bash curl -s -X POST https://api.invisible.app/api/department-access/revoke \ -H "Authorization: Bearer icap_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "userId": "c3d4e5f6-0001-4000-8000-000000000001", "departments": ["Marketing"] }' ``` **Response:** ```json { "revoked": 1 } ``` --- ### GET /api/department-access List all department access grants. **Auth:** Required. `owner` or `admin` role. **Query params:** | Param | Type | Description | |-------|------|-------------| | `userId` | uuid | Filter to a specific user | ```bash curl -s "https://api.invisible.app/api/department-access?userId=c3d4e5f6-0001-4000-8000-000000000001" \ -H "Authorization: Bearer icap_YOUR_KEY" ``` **Response:** ```json { "departmentAccess": [ { "id": "...", "userId": "c3d4e5f6-0001-4000-8000-000000000001", "department": "Sales", "grantedBy": "...", "createdAt": "2026-04-06T00:00:00Z" } ] } ``` --- ## Error Responses All errors follow this format: ```json { "error": "Description of what went wrong" } ``` | Status | Meaning | |--------|---------| | 400 | Bad request (missing fields, invalid data) | | 401 | Missing/invalid auth token | | 403 | Insufficient permissions for this action | | 404 | Resource not found |