Skip to main content
wefunder/api

Your Wefunder data,in your tools.

Connect your Wefunder portfolio, syndicate, or raise to the tools you already use.

Scoped access. Live webhooks. Human-approved writes.

Built for

Who this is for

Quickstart

Create an app, then make your first call

Almost everything in the API belongs to a user, a company, or a syndicate, and your app reaches one by being installed on it. An installation is the connection: your app, one user or company or syndicate, and the scopes they granted. It shows up under their Installed apps, routes their webhooks to you, and lasts until either side revokes it. A token is what you call with, and every token comes from an installation. Public deal data is the one exception: it needs no install at all.

1

Create an app

Register your app in the developer portal. You get a test key (pk_test_ / sk_test_) and a live key (pk_live_ / sk_live_) the moment it exists. Live keys work right away on companies and syndicates your own organization manages; app review is only needed to be installed on someone else's.

2

Pick your first call

What you build decides which token you need. Three tracks; each ends in a request that returns something real. Founders syncing their own company have a shorter route that never leaves the portal: the recipe does the install and the token from there.

You are buildingFirst callTrack
Deal discovery, no Wefunder user involvedGET /exploreExplore the catalog
A view of an investor's own holdingsGET /portfolioRead a user's portfolio
Your own company's investments in a CRM or spreadsheetGET /investmentsSync investments to your CRM (portal-first, no OAuth)
Tooling for a company or syndicate you run or serve, from codeGET /investments, GET /syndicates/{id}/dealsAct for a company or syndicate

Explore the catalog​

No user, no install. Exchange your key for a read:public token and read what an anonymous visitor sees on wefunder.com/explore. Private rounds are never included.

Public catalog
import { Wefunder } from "@wefunder/sdk";   // npm install @wefunder/sdk

const wf = await Wefunder.fromClientCredentials({
clientId: process.env.WEFUNDER_CLIENT_ID,
clientSecret: process.env.WEFUNDER_CLIENT_SECRET,
scopes: ["read:public"],
});

for await (const offering of wf.offerings.all()) {
console.log(offering.id, offering.attributes?.company_name);
}

This is the whole track. For filters, offering detail, and pagination see the Explore API guide. An app-only token cannot read anything tied to a user; for that, keep going.

Read a user's portfolio​

The investor authorizes your app once through OAuth 2.0 Authorization Code with PKCE. That consent screen is the installation on the user. There is nothing to call on /installations for this case; the token you get back already reaches what that user can see, and only that.

Authorize, exchange, read
import { Wefunder, generatePkce, createAuthorizationUrl, exchangeCode } from "@wefunder/sdk";

// 1. Send the investor to consent. Keep `state` and the PKCE verifier in their session.
// (A pk_test_ client id picks the sandbox authorize host for you.)
const pkce = generatePkce();
const state = crypto.randomUUID();
const authorizationUrl = createAuthorizationUrl({
clientId: process.env.WEFUNDER_CLIENT_ID,
redirectUri: REDIRECT_URI,
scopes: ["read:investments"],
state,
pkce,
});

// 2. On the callback, exchange the code (after checking `state` matches the session)
const tokens = await exchangeCode({
clientId: process.env.WEFUNDER_CLIENT_ID,
clientSecret: process.env.WEFUNDER_CLIENT_SECRET,
code,
redirectUri: REDIRECT_URI,
codeVerifier: pkce.codeVerifier,
});

// 3. Read their holdings. The SDK refreshes and rotates the tokens; persist every set it hands you.
const wf = new Wefunder({
tokens,
clientId: process.env.WEFUNDER_CLIENT_ID,
clientSecret: process.env.WEFUNDER_CLIENT_SECRET,
store: { save: (next) => persistTokens(next) },
});
const portfolio = await wf.portfolio.get();
console.log(portfolio.attributes);

The access token lasts two hours; the refresh token renews it until the investor revokes your app under Installed apps. GET /portfolio/positions lists each position with per-security detail. Portfolio endpoints are beta: shapes may still change. See Investor portfolio and Authentication.

Act for a company or syndicate​

Here the installation is explicit, and it mints a token that acts as the company or syndicate rather than as a person. This track is live-only today: installs and installation tokens are not yet available in sandbox, so use your live key on a company or syndicate your organization manages.

The code below is the syndicate case, installed from a user token. Syncing your own company? You do not need any of it: Sync investments to your CRM installs and mints the token from the portal with no OAuth, then calls GET /investments. Come back here when you install on many companies from code; for a company the same calls take target_type: "company", a company id, and read:investments.

1

Install your app on the company or syndicate

Two ways, same result. From the portal: pick the app in the sidebar, open its Installations page, and press Install next to one of your own companies or syndicates; or copy the install link there and send it to the founder or syndicate lead, who signs in, picks the target, and consents. From code: with a user token holding read:installations write:installations (both: listing needs the read scope and the write scope does not imply it), list the companies and syndicates that user may install on, then install. The list holds only companies and syndicates, so it is empty for a user who runs neither. Step by step, both ways: Install your app.

Programmatic install
// wf holds the manager's user token (read:installations write:installations)
const targets = await wf.installations.eligibleTargets({ target_type: "syndicate" });
for (const target of targets) console.log(target.id, target.name, target.tier);

const install = await wf.installations.create({
target_type: "syndicate", target_id: "SYNDICATE_ID", scopes: ["read:syndicates"],
});
console.log(install.data.id, install.token.access_token); // the token appears here once

Who may install: anyone who can edit the company, or a syndicate manager. An install never grants more than the installer holds.

2

Get the installation token

A programmatic install returns the token in its response, once. The install link does not show a token. If your app has a setup URL, Wefunder sends the person there after consent with the new installation_id; portal-created apps cannot set one yet, so plan on the fallback: list your app's installations with the manager's user token, take the new install's id, and mint. The credential is the response's token.access_token; the data object is the install itself.

Mint a token for an installation
// Match the active install on this syndicate; the list is newest-first and also
// holds revoked rows and user installs, so never pick by position.
const installs = await wf.installations.list();
const install = installs.data.find(
(i) => i.attributes.status === "active" && i.attributes.target.id === "SYNDICATE_ID",
);
if (!install) throw new Error("not installed on SYNDICATE_ID yet");

const minted = await wf.installations.mintToken(install.id);
const INSTALLATION_TOKEN = minted.token.access_token; // store this; it is shown once

The token has no expiry and no refresh; revoking the install revokes it.

3

Make a request as the company or syndicate

First request
const asSyndicate = new Wefunder({ accessToken: INSTALLATION_TOKEN });
const deals = await asSyndicate.unwrap(
asSyndicate.raw.listSyndicateDeals({ path: { syndicate_id: "SYNDICATE_ID" } }),
);
for (const deal of deals.data) console.log(deal.id, deal.attributes.name);

For a company install the equivalent is GET /investments, which returns that company's records and nothing else; Sync investments to your CRM takes that call through backfill, cursor sync, and the webhook. Register a webhook endpoint once and every installed company's or syndicate's events arrive there, signed. See Installations and Webhooks.

Environments

Sandbox and live

Every app gets sandbox and live credentials the moment it's created. One API host serves both; the credential prefix selects the environment.

EnvironmentCredentialsAccess tokensAuthorize URL
Sandboxpk_test_ / sk_test_at_test_https://oauth.wefunder-sandbox.com/oauth/authorize
Livepk_live_ / sk_live_at_live_https://wefunder.com/oauth/authorize

Sandbox is your own seeded realm with its own logins, and nothing you do there touches a real account. The explore and portfolio tracks work there today. Installations and their tokens are live-only for now, so the company and syndicate track runs against live keys on a company or syndicate your own organization manages. See Sandbox.

Reference

Documentation

Preview

Partner SPV API

For platforms that want to create SPVs, invite investors through their own UX, and let Wefunder handle the contracts, escrow, compliance, and cap table. This surface is in invite-only preview: the endpoints appear in the API reference only for apps with preview access, and the request and response shapes may still change.

Apply for preview access.

Get started

Request access​

Run a company or a syndicate on Wefunder? You already have access: sign in at the developer portal with the account you use to manage it and create your first app. No waitlist.

Everyone else, tell us what you want to build. We review requests for API access and for the Partner SPV preview from this one form.

Wefunder APIWefunder API
Which tools would you connect? (optional)