API v1

API docs for funds and fund administrators

This API is designed for high-volume funds and fund administrators.

Quickstart 1: Get your API key
Generate keys in Settings → API. Key values display once.
Authorization: Bearer fip_live_...
Quickstart 2: Download report PDF
Download a filing report for a firm and reporting year.
curl -L -H "Authorization: Bearer $API_KEY" \
  -o ca-vcc-report.pdf \
  "http://localhost:3000/api/v1/firms/{firmId}/report?year=2025"

Management API Reference

This document defines the public management API under /api/v1/ for high-volume funds and fund administrators.

Base URL and Version

  • Base path: /api/v1/
  • Versioning: path versioning (v1)

Authentication and Authorization

  • Auth mode: API key
  • Header: Authorization: Bearer <api_key>
  • API keys are user-scoped and inherit that user's firm access
  • Firm on the API key must be on the enterprise plan
  • Role rules:
    • admin: read and write
    • member: read-only
  • Common auth/permission responses:
    • 401 missing or invalid API key
    • 402 payment required (firm is not on enterprise plan)
    • 403 key is valid but does not have required access
    • 404 resource is not in caller scope

Basic Firm Management

The Basic Notes

  • Every firm is isolated in API scope.
  • Callers only see firms they are authorized to access.
  • firmId is the required scope key for firm-level operations.
  • Report PDFs are downloaded with GET /api/v1/firms/{firmId}/report?year=YYYY.

Firm Management for Fund Administrators

Concept: External Reference ID

externalReferenceId is an optional caller-provided identifier for matching a firm in your internal system.

Rules:

  • Use a stable, unique value from your system (example: CRM org ID).
  • Do not include sensitive personal data.
  • Treat this as an idempotency-friendly mapping key for retries and reconciliation.

Create Firm

POST /api/v1/firms

Request body:

{
  "name": "Acme Ventures",
  "website": "https://acme.vc",
  "headquartersLocation": "San Francisco, CA",
  "externalReferenceId": "crm_firm_93214"
}

Successful response (201):

{
  "firm": {
    "id": "firm_123",
    "name": "Acme Ventures",
    "website": "https://acme.vc",
    "headquartersLocation": "San Francisco, CA",
    "externalReferenceId": "crm_firm_93214",
    "createdAt": "2026-02-12T00:00:00.000Z"
  }
}

Validation notes:

  • name is required.
  • externalReferenceId should be unique within your tenant context.
  • Return 409 when a duplicate mapping key is submitted.

API Reference

The endpoints below cover the public /api/v1 surface.

Common Headers

Use these headers unless an endpoint says otherwise.

HeaderRequiredValue
AuthorizationYesBearer <api_key>
Content-TypeFor POST requestsapplication/json
AcceptRecommendedapplication/json

1. List Firms

GET /api/v1/firms

Purpose: list firms accessible to the authenticated key.

Sample request:

curl -H "Authorization: Bearer $API_KEY" \
  "$BASE_URL/api/v1/firms"

Sample response (200):

{
  "firms": [
    {
      "id": "firm_123",
      "name": "Acme Ventures",
      "website": "https://acme.vc",
      "headquartersLocation": "San Francisco, CA",
      "externalReferenceId": "crm_firm_93214",
      "createdAt": "2026-02-12T00:00:00.000Z"
    }
  ]
}

2. Create Firm

POST /api/v1/firms

Purpose: create a firm workspace.

Required headers:

  • Authorization: Bearer <api_key>
  • Content-Type: application/json

Sample request:

curl -X POST "$BASE_URL/api/v1/firms" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Ventures",
    "website": "https://acme.vc",
    "headquartersLocation": "San Francisco, CA",
    "externalReferenceId": "crm_firm_93214"
  }'

Sample response (201):

{
  "firm": {
    "id": "firm_123",
    "name": "Acme Ventures",
    "website": "https://acme.vc",
    "headquartersLocation": "San Francisco, CA",
    "externalReferenceId": "crm_firm_93214",
    "createdAt": "2026-02-12T00:00:00.000Z"
  }
}

3. List Funds

GET /api/v1/firms/{firmId}/funds

Purpose: list funds in a firm.

Sample request:

curl -H "Authorization: Bearer $API_KEY" \
  "$BASE_URL/api/v1/firms/firm_123/funds"

Sample response (200):

{
  "funds": [
    {
      "id": "fund_456",
      "firmId": "firm_123",
      "name": "Acme Opportunity Fund I",
      "isCoveredEntity": true,
      "legalName": "Acme Opportunity Fund I, L.P.",
      "pointOfContactEmail": "[email protected]",
      "designatedEmail": "[email protected]",
      "website": "https://acme.vc",
      "createdAt": "2026-02-12T00:00:00.000Z"
    }
  ]
}

4. Create Fund

POST /api/v1/firms/{firmId}/funds

Purpose: create a fund under a firm.

Required headers:

  • Authorization: Bearer <api_key>
  • Content-Type: application/json

Sample request:

curl -X POST "$BASE_URL/api/v1/firms/firm_123/funds" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Opportunity Fund I",
    "isCoveredEntity": true,
    "legalName": "Acme Opportunity Fund I, L.P.",
    "pointOfContactName": "Jane Doe",
    "pointOfContactTitle": "COO",
    "pointOfContactEmail": "[email protected]",
    "designatedEmail": "[email protected]",
    "designatedPhone": "+1-555-555-5555",
    "designatedAddress": "123 Main St, San Francisco, CA",
    "website": "https://acme.vc"
  }'

Sample response (201):

{
  "fund": {
    "id": "fund_456",
    "firmId": "firm_123",
    "name": "Acme Opportunity Fund I",
    "isCoveredEntity": true,
    "legalName": "Acme Opportunity Fund I, L.P.",
    "pointOfContactEmail": "[email protected]",
    "designatedEmail": "[email protected]",
    "createdAt": "2026-02-12T00:00:00.000Z"
  }
}

5. List Portfolio Companies

GET /api/v1/firms/{firmId}/portcos

Purpose: list portfolio companies for a firm.

Query params:

  • year optional, defaults to prior calendar year
  • fundId optional fund filter

Sample request:

curl -H "Authorization: Bearer $API_KEY" \
  "$BASE_URL/api/v1/firms/firm_123/portcos?year=2025"

Sample response (200):

{
  "portcos": [
    {
      "id": "portco_789",
      "firmId": "firm_123",
      "fundId": "fund_456",
      "reportingYear": 2025,
      "legalName": "Example Labs Inc.",
      "principalPlaceOfBusiness": "San Francisco, CA",
      "amountInvestedUsdCents": 5000000,
      "foundersTotalKnown": true,
      "foundersTotal": 2,
      "createdAt": "2026-02-12T00:00:00.000Z"
    }
  ]
}

6. Create Portfolio Company

POST /api/v1/firms/{firmId}/portcos

Purpose: create a portfolio company row for a reporting year.

Required headers:

  • Authorization: Bearer <api_key>
  • Content-Type: application/json

Sample request:

curl -X POST "$BASE_URL/api/v1/firms/firm_123/portcos" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fundId": "fund_456",
    "reportingYear": 2025,
    "legalName": "Example Labs Inc.",
    "principalPlaceOfBusiness": "San Francisco, CA",
    "amountInvestedUsdCents": 5000000,
    "foundersTotalKnown": true,
    "foundersTotal": 2
  }'

Sample response (201):

{
  "portco": {
    "id": "portco_789",
    "firmId": "firm_123",
    "fundId": "fund_456",
    "reportingYear": 2025,
    "legalName": "Example Labs Inc.",
    "principalPlaceOfBusiness": "San Francisco, CA",
    "amountInvestedUsdCents": 5000000,
    "foundersTotalKnown": true,
    "foundersTotal": 2,
    "createdAt": "2026-02-12T00:00:00.000Z"
  }
}

7. Add Team Member

POST /api/v1/firms/{firmId}/team-members

Purpose: add a team member to a firm.

Required headers:

  • Authorization: Bearer <api_key>
  • Content-Type: application/json

Sample request:

curl -X POST "$BASE_URL/api/v1/firms/firm_123/team-members" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "name": "GP Name",
    "role": "member",
    "sendInviteEmail": true
  }'

Sample response (201):

{
  "teamMember": {
    "id": "team_member_123",
    "userId": "user_123",
    "email": "[email protected]",
    "name": "GP Name",
    "role": "member",
    "status": "active",
    "createdAt": "2026-02-12T00:00:00.000Z"
  }
}

8. Remove Team Member

DELETE /api/v1/firms/{firmId}/team-members/{teamMemberId}

Purpose: remove a team member from a firm.

Sample request:

curl -X DELETE \
  -H "Authorization: Bearer $API_KEY" \
  "$BASE_URL/api/v1/firms/firm_123/team-members/team_member_123"

Sample response (200):

{
  "deletedTeamMemberId": "team_member_123"
}

9. Get Year Readiness

GET /api/v1/firms/{firmId}/year-readiness?year=YYYY

Purpose: return filing readiness status and blockers for a firm-year.

Sample request:

curl -H "Authorization: Bearer $API_KEY" \
  "$BASE_URL/api/v1/firms/firm_123/year-readiness?year=2025"

Sample response (200):

{
  "readiness": {
    "firmId": "firm_123",
    "year": 2025,
    "status": "BLOCKED",
    "blockers": [
      "No covered funds marked for reporting.",
      "Missing point of contact email for one or more covered funds."
    ],
    "defaultSubmissionLink": "https://compliance.fipvcc.com/survey/abc123",
    "counts": {
      "funds": 3,
      "coveredFunds": 2,
      "portcos": 14,
      "portcosWithResponses": 10
    }
  }
}

10. Download Report PDF

GET /api/v1/firms/{firmId}/report?year=YYYY

Purpose: download the combined filing report PDF.

Required headers:

  • Authorization: Bearer <api_key>
  • Accept: application/pdf recommended

Sample request:

curl -L \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/pdf" \
  -o "firm_123-2025-ca-vcc-report.pdf" \
  "$BASE_URL/api/v1/firms/firm_123/report?year=2025"

Successful response:

  • Status: 200
  • Content-Type: application/pdf
  • Content-Disposition: attachment; filename="firm_123-2025-ca-vcc-report.pdf"

Blocker response (409):

{
  "error": "Report generation is blocked until readiness blockers are resolved."
}

Error Shape

Sample JSON error response:

{
  "error": "Human readable message",
  "code": "OPTIONAL_MACHINE_CODE"
}

Example payment-required response (402):

{
  "error": "Payment required. API access is only available on the enterprise plan.",
  "code": "PAYMENT_REQUIRED"
}