Developers

Your data, in your own stack.

A read-only REST API for your pipeline and portfolio, and signed webhooks for the moments that matter. Included with the Institutional plan, or as an add-on to Firm for $300 a month.

Quickstart

An admin creates a key in the app under Settings, Developers. The key is shown once, so store it somewhere safe. Then call the API with the key as a bearer token.

curl "https://app.venturefract.com/api/v1/deals?limit=2" \
  -H "Authorization: Bearer vfk_your_key_here"
{
  "data": [
    { "id": "6f1c…", "name": "Northlight AI", "stage": "Diligence", "round": "Series A", "ask": 6.5, "fund_id": "a2b9…", "created_at": "2026-09-14T09:12:03Z" },
    { "id": "9d03…", "name": "Harbor Robotics", "stage": "Screening", "round": "Seed", "ask": 3.0, "fund_id": "a2b9…", "created_at": "2026-09-20T16:41:55Z" }
  ],
  "next_cursor": "OWQwMy4uLg"
}

The example is illustrative. Your responses contain your own records.

Authentication and limits

  • Send Authorization: Bearer vfk_… on every request. Keys belong to one firm and can only read that firm's data.
  • The API is read-only: only GET requests are accepted.
  • Each key is limited to 120 requests per minute. Over the limit you receive 429 with a Retry-After header.
  • You can create up to 10 active keys and revoke any of them instantly. A revoked key stops working at once.
  • If the firm's plan no longer includes API access, requests return 403 until it does.

Pagination and incremental sync

List endpoints return data and next_cursor. Pass the cursor back as ?cursor= to get the next page. When next_cursor is null you have everything.

  • limit: 1 to 200, default 50.
  • updated_since: an ISO 8601 timestamp. Returns only records changed at or after it, which is the efficient way to keep a warehouse in sync.
  • stage (deals only): filter by pipeline stage.
  • Records are returned in a stable order, so paging never skips or repeats a record that existed when you started.

Resources

EndpointReturns
GET /api/v1/meThe firm the key belongs to: id, name, base_currency.
GET /api/v1/deals
GET /api/v1/deals/{id}
id, name, stage, round, sector, geo, ask, source, next_step, next_step_due, owner_membership_id, fund_id, company_id, website, one_liner, thesis_note, created_at, updated_at, archived_at
GET /api/v1/companies
GET /api/v1/companies/{id}
id, name, sector, geo, health, created_at, updated_at, archived_at
GET /api/v1/positions
GET /api/v1/positions/{id}
id, company_id, fund_id, round, invested_amount, invested_at, exited_at, pro_rata_right, information_right, board_right, created_at, updated_at
GET /api/v1/funds
GET /api/v1/funds/{id}
id, name, vintage_year, status, strategy, currency, created_at, updated_at, archived_at

Monetary amounts are in the units and currency your firm uses in the app.

Errors

Errors use one shape, with a request id you can quote if you need help.

{ "error": { "code": "unauthorized", "message": "This API key is not valid or has been revoked.", "request_id": "8c496e0d-6800-41a1-8db7-7b7a7d39f996" } }
StatusCodeMeaning
400bad_requestA parameter is invalid, such as a limit over 200 or a malformed cursor.
401unauthorizedThe key is missing, invalid or revoked.
403forbiddenThe firm's plan does not include API access.
404not_foundUnknown resource, or no such record in your firm.
405method_not_allowedThe API is read-only.
429rate_limitedOver 120 requests per minute for this key.

Webhooks

Add an HTTPS endpoint under Settings, Developers and choose the events you want. We send a signed POST with a JSON body.

EventSent when
deal.createdA deal is added to the pipeline.
deal.stage_changedA deal moves to a different stage. Includes previous_stage.
position.createdA portfolio position is added.
update.submittedA founder submits an update.
{
  "id": "evt_5c364e15362b419efa67bc53",
  "type": "deal.stage_changed",
  "created_at": "2026-10-06T12:59:46Z",
  "data": { "id": "a8fe…", "name": "Northlight AI", "stage": "Screening", "previous_stage": "Sourcing", "fund_id": "8d4a…" }
}
  • Respond with any 2xx within 8 seconds. Redirects are not followed.
  • Failed deliveries are retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 24 hours, then marked failed. That is 7 attempts over about 34 hours.
  • The event id is the same on every retry, so use it to ignore duplicates.
  • An endpoint that fails 20 deliveries in a row is paused. Resume it in the app.
  • URLs must be HTTPS on the standard port with a public hostname. Addresses and hostnames that point to private networks are refused.
  • Each request carries VentureFract-Event, VentureFract-Delivery and VentureFract-Signature headers.

Verifying signatures

Always verify a webhook before trusting it. The signature header looks like t=1791290970,v1=9f2c…. Compute an HMAC-SHA256, using your endpoint's signing secret, of the timestamp, a dot and the raw request body, and compare it to v1 in constant time. Reject anything with a timestamp more than five minutes old.

Node.js

import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(secret, header, rawBody) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return expected.length === v1.length && timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}

Python

import hmac, hashlib, time

def verify(secret: str, header: str, raw_body: bytes) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    if abs(time.time() - int(parts["t"])) > 300:
        return False
    expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])

Your signing secret is shown once when you create the endpoint. If it is ever exposed, rotate it from the endpoint's menu in the app.

Build on your own data.

Create your firm and explore the product with your own deals. The API comes with the Institutional plan or as a Firm add-on.

PricingCreate your firm