Developer guide
Read your cap table, your documents, and your own holdings from a script, or from an AI assistant. One personal key authenticates both the REST API and the MCP server. Every surface is read only.
A key carries your own access and nothing more. In each organization it gets the role you already hold. It also reads your own holder portfolio. No key can record a transaction, change a setting, read the audit log, or open the diligence bundle.
Create a key on the personal API keys page. We show the key once. Copy it, then store it in a password manager or a secret manager. We keep only the SHA-256 hash of the key, so we cannot show it again.
Send the key in the Authorization header on every request:
curl -H "Authorization: Bearer cdu_..." \
https://capdaddy.cc/api/v1/meRevoke a key at any time on the same page. Revocation takes effect on the next request. Your role is resolved again on every request, so a role change applies immediately.
Replace {org} with the organization id from /api/v1/orgs. The role column is the role you need in that organization.
| Endpoint | Role | What it returns |
|---|---|---|
| GET /api/v1/me | Any key | Your identity, your organizations, and your holder organizations. |
| GET /api/v1/orgs | Any key | The organizations this key can read, each with your role. |
| GET /api/v1/orgs/{org}/captable | Viewer | The cap table as of a date, by class and by stakeholder. |
| GET /api/v1/orgs/{org}/stakeholders | Viewer | The stakeholder directory. |
| GET /api/v1/orgs/{org}/stakeholders/{id} | Viewer | One stakeholder with their holdings. |
| GET /api/v1/orgs/{org}/securities | Viewer | Every security with its resolved totals. |
| GET /api/v1/orgs/{org}/securities/{id} | Viewer | One security with its vesting and lifecycle detail. |
| GET /api/v1/orgs/{org}/register | Viewer | The securities register: every security ever issued, with its consideration and disposition. |
| GET /api/v1/orgs/{org}/events | Viewer | The ledger event feed, oldest first. Bound it with from and to, then page with cursor. Convertible instrument events and organization-level override events need the admin role, and convertible instrument events also need the SAFEs and notes feature. |
| GET /api/v1/orgs/{org}/documents | Viewer | The document index. Filter it with stakeholderId. |
| GET /api/v1/orgs/{org}/documents/{id}/download | Viewer | The bytes of one document. |
| GET /api/v1/orgs/{org}/consents | Viewer | Board and stockholder consents with their status. |
| GET /api/v1/orgs/{org}/meetings | Viewer | Board meetings with their minutes status. |
| GET /api/v1/orgs/{org}/convertibles | Admin | Every SAFE and convertible note, with live accrual on the outstanding ones. The asOf date sets the date interest is accrued to and hides an instrument issued after it, the status always describes the instrument today, and a date in the future answers 422. |
| GET /api/v1/orgs/{org}/rounds | Admin | The fundraising rounds, with their terms and the capital each close banked. |
| GET /api/v1/orgs/{org}/compliance | Admin | The compliance calendar: 409A, Rule 701, 83(b), exercise windows, and open tasks. |
| GET /api/v1/orgs/{org}/valuations | Admin | The 409A and fair market value history, newest effective date first. |
| GET /api/v1/orgs/{org}/search | Viewer | Search people, securities, consents, and documents. Send q. |
| GET /api/v1/orgs/{org}/board/members | Owner | The directors of record. |
| GET /api/v1/orgs/{org}/exports/{kind} | Viewer | One export artifact. See the export kinds below. |
| GET /api/v1/portfolio | Holder | Your own holdings across every issuer, by your email. |
| GET /api/v1/portfolio/statement | Holder | Your own consolidated holder statement, as a PDF. |
An organization manager can switch the member API off for their organization. The organization then disappears from your list, and its endpoints answer 404. Your own holder portfolio is not affected.
| Name | Values | What it does |
|---|---|---|
| asOf | YYYY-MM-DD | The legal as-of date, in America/New_York. It defaults to today. Cap table, securities, documents, compliance, convertibles, and exports accept it. The convertibles surface refuses a date in the future, because it reports interest accrued to that date. |
| mode | effective | recorded | How the ledger is replayed. "effective" uses legal dates. "recorded" uses recording times. It defaults to effective. |
| basis | fullyDiluted | outstanding | The cap table basis. It defaults to fullyDiluted. |
| q | text | The search query. Send at least 2 characters. Longer queries are cut at 200 characters. |
| stakeholderId | uuid | Limits the document index to one stakeholder. |
| from | YYYY-MM-DD | The first effective date the event feed reports. Events on this date are included. |
| to | YYYY-MM-DD | The last effective date the event feed reports. Events on this date are included. |
| kinds | comma-separated list | Limits the event feed to these event kinds. Send the values as one list, or repeat the parameter. An unknown kind answers 422, and the message names every kind the feed accepts. A kind your role or your plan does not cover also answers 422, and the message names what it needs. |
| limit | 1 to 1000 | How many events one page of the feed returns. It defaults to 200. A larger value is cut to 1000. |
| cursor | opaque text | The next page of the event feed. Send back the nextCursor value from the previous reply. The reply sets truncated to true while pages remain. |
curl -H "Authorization: Bearer cdu_..." \
"https://capdaddy.cc/api/v1/orgs/<org>/captable?asOf=2026-06-30&basis=outstanding"Every share count and every money amount crosses the wire as an exact decimal STRING. We never send a floating point number, because a float cannot hold a cent or a share exactly. Parse these values with a decimal library, or keep them as strings. Do not call parseFloat on them.
{
"outstanding": "1750000",
"fullyDiluted": "2431250",
"pricePerShare": "1.2500000000"
}Seven rules cover the fields that are easy to misread. Follow each one before you put a number in front of an investor.
"51.282051" means 51.282051 percent. It does not mean 0.51282051. Do not multiply it by 100 again.pctOfBasisTotal divides by the total on the basis you asked for, so its numerator and its denominator always describe the same basis. pctOfAsConvertedFullyDiluted divides by the as-converted fully diluted total. Use the as-converted figure to compare holders across classes that convert at different ratios.asConvertedFullyDiluted restates a position in common-equivalent shares. It multiplies each class by that class conversion ratio, so the result can be fractional. Sum this column over every holder and you get the as-converted total exactly.derived means a transfer or a conversion minted the shares, so the holder paid the company nothing. Never add a derived amount into cash invested."0". A note accrues interest, and the reply gives the interest to the report date plus the current balance. An instrument that already converted or was repaid reports null for both, because accrual stopped at that event.| Status | Body | What it means |
|---|---|---|
| 200 | The JSON payload, or the file bytes | The read succeeded. Your reads are written to the organization audit log, with you as the actor and the key as the subject. The log records one entry for each hour in which you read a surface. It does not record one entry for each request. A file download and an export always record one entry for each access. |
| 401 | {"error":"invalid_token"} | The MCP server refused the request. Two causes give the same answer. First, the key is wrong, revoked, or expired. Second, too many MCP requests came from your address: the budget is 600 requests per hour, and over it the server answers 401, not 429. Check the key. If the key is good, wait, then retry. The REST endpoints are not affected: they answer 404 for a bad key and 429 over their own budget. |
| 404 | {"error":"not_found"} | One opaque answer for every miss: no key, a bad key, a revoked key, an expired key, an organization you are not a member of, a role below the endpoint, an organization that switched member API access off, a suspended organization, or an unknown record. The response never says which. |
| 402 | {"error":"feature_locked","feature":"..."} | You proved your membership, and the organization plan does not include this surface. Upgrade the plan, then retry. |
| 422 | {"error":"<code>","message":"..."} | The request was authorized, and the artifact could not be built. The code names the reason, for example OCF_NOT_CONFORMANT. |
| 429 | {"error":"rate_limited"} | Too many requests from your address. JSON reads allow 600 per hour. Exports allow 60 per hour. Each MCP tool call counts as one JSON read. Wait, then retry. |
Request an export at /api/v1/orgs/{org}/exports/{kind}. The response is the file itself. Some kinds need a paid plan, and an unentitled request answers 402.
| Kind | What it contains |
|---|---|
| cap-table.csv | Cap table totals by class and by stakeholder. |
| securities-ledger.csv | Every security with its per-instrument totals. |
| stakeholders.csv | The stakeholder directory. |
| securities-register.csv | The stock register, as CSV. |
| securities-register.pdf | The stock register, as a printable PDF. |
| captable-pdf | A point-in-time cap table snapshot. |
| captable-xlsx | The cap table in the lawyer workbook format. |
| ledgers-xlsx | The securities, plan, and pool transaction ledgers. |
| ocf | The Open Cap Format package, validated against the official schemas. |
| backup | The full backup: documents, ledgers, OCF, and the cap table. |
| 409a-package.zip | The 409A valuation data package. |
| minute-book.zip | The indexed corporate minute book. |
The audit log and the diligence bundle are not on this list. Both need a fresh confirmation in the product, so no long lived key can reach them.
The MCP server gives an AI assistant the same read tools, over the same key. Point your client at this URL and send your key in the Authorization header:
https://capdaddy.cc/api/mcp/mcpEach tool reads one organization. Pass the organization id from list_orgs. A tool answers the text not_found for every miss, the same way the REST endpoints answer 404.
| Tool | Role | What it returns |
|---|---|---|
| whoami | Any key | Your identity, your organizations, and your holder organizations. |
| list_orgs | Any key | The organizations this key can read, each with your role. |
| get_cap_table | Viewer | The cap table as of a date, by class and by stakeholder. |
| list_stakeholders | Viewer | The stakeholder directory. |
| get_stakeholder | Viewer | One stakeholder with their holdings. |
| list_securities | Viewer | Every security with its resolved totals. |
| get_security | Viewer | One security with its vesting and lifecycle detail. |
| get_register | Viewer | The securities register: every security ever issued, with its consideration and disposition. |
| list_events | Viewer | The ledger event feed, oldest first. It answers what changed since a date. Convertible instrument events and organization-level override events need the admin role, and convertible instrument events also need the SAFEs and notes feature. |
| list_documents | Viewer | The document index. It returns metadata only, never the file. |
| list_consents | Viewer | Board and stockholder consents with their status. |
| list_meetings | Viewer | Board meetings with their minutes status. |
| list_export_kinds | Viewer | The export catalog, with the REST address that serves each file. |
| search | Viewer | People, securities, consents, and documents that match your text. |
| list_convertibles | Admin | Every SAFE and convertible note, with live accrual on the outstanding ones. The asOf date sets the date interest is accrued to and hides an instrument issued after it, the status always describes the instrument today, and a date in the future is refused. |
| list_rounds | Admin | The fundraising rounds, with their terms and the capital each close banked. |
| get_compliance_summary | Admin | The compliance calendar: 409A, Rule 701, 83(b), exercise windows, and open tasks. |
| list_valuations | Admin | The 409A and fair market value history, newest effective date first. |
| list_board_members | Owner | The directors of record. |
| get_my_portfolio | Holder | Your own holdings across every issuer, by your email. |
The MCP server sends text only. It never sends a file. Call list_export_kinds to learn which export files exist, then fetch the one you want from the REST endpoint with the same key. No tool writes data.
Run one command:
claude mcp add --transport http capdaddy https://capdaddy.cc/api/mcp/mcp \
--header "Authorization: Bearer cdu_..."Claude Desktop connects to a remote server through mcp-remote. Open Settings, then Developer, then Edit Config. Add this server, then restart Claude Desktop.
{
"mcpServers": {
"capdaddy": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://capdaddy.cc/api/mcp/mcp",
"--header",
"Authorization:${AUTH_HEADER}"
],
"env": {
"AUTH_HEADER": "Bearer cdu_..."
}
}
}
}Put your key in the env block, and leave no space after the colon in the header argument. On Windows, the client does not escape a space inside an argument, and a header written in one piece arrives broken.
Add the server to .cursor/mcp.json in your project, or to ~/.cursor/mcp.json for every project.
{
"mcpServers": {
"capdaddy": {
"url": "https://capdaddy.cc/api/mcp/mcp",
"headers": {
"Authorization": "Bearer cdu_..."
}
}
}
}Add the server to .vscode/mcp.json, then start it from the editor.
{
"servers": {
"capdaddy": {
"type": "http",
"url": "https://capdaddy.cc/api/mcp/mcp",
"headers": {
"Authorization": "Bearer cdu_..."
}
}
}
}Add the server to opencode.json in your project, or to ~/.config/opencode/opencode.json for every project.
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"capdaddy": {
"type": "remote",
"url": "https://capdaddy.cc/api/mcp/mcp",
"enabled": true,
"oauth": false,
"headers": { "Authorization": "Bearer cdu_..." }
}
}
}Keep oauth set to false. OpenCode tries OAuth first on a remote server, and this server accepts a bearer key only.
Codex reads the key from an environment variable. Add this line to your shell profile, then open a new terminal.
export CAPDADDY_API_KEY="cdu_..."Then add the server to ~/.codex/config.toml.
[mcp_servers.capdaddy]
url = "https://capdaddy.cc/api/mcp/mcp"
bearer_token_env_var = "CAPDADDY_API_KEY"The config file holds the name of the variable, never the key itself.
The connectors on claude.ai need OAuth. This server authenticates with a bearer key, so the web connectors cannot use it yet. Use Claude Code, Claude Desktop, Cursor, VS Code, OpenCode, or the OpenAI Codex CLI.
Tell us what you are building. We answer every message, usually within one business day. The rest of the product documentation lives in the help center.
[email protected]