@wefunder/sdk 0.1.0-beta.10 → 0.1.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,12 +2,12 @@
2
2
  "manifestVersion": 1,
3
3
  "lang": "JavaScript",
4
4
  "label": "@wefunder/sdk",
5
- "sdkVersion": "0.1.0-beta.10",
5
+ "sdkVersion": "0.1.0-beta.12",
6
6
  "apiVersion": "2025-01-15",
7
7
  "generatedBy": "scripts/build-examples-manifest.mjs",
8
8
  "samples": {
9
- "createInstallation": "const install = await wf.unwrap(\n wf.raw.createInstallation({\n body: { target_type: \"company\", target_id: \"co_abc123Example\", scopes: [\"read:offerings\", \"read:investments\"] },\n }),\n);\nconsole.log(install.data?.id, install.data?.attributes);",
10
- "createInstallationToken": "const token = await wf.unwrap(\n wf.raw.createInstallationToken({ path: { external_id: \"ins_9t2xExample\" }, body: { scopes: [\"read:investments\"] } }),\n);\nconsole.log(token.data);",
9
+ "createInstallation": "const install = await wf.installations.create({\n target_type: \"company\",\n target_id: \"co_abc123Example\",\n scopes: [\"read:offerings\", \"read:investments\"],\n});\nconsole.log(install.data?.id, install.token?.access_token); // the token is shown once — store it",
10
+ "createInstallationToken": "const minted = await wf.installations.mintToken(\"ins_9t2xExample\", [\n \"read:investments\",\n]);\nconsole.log(minted.token?.access_token); // shown once — store it",
11
11
  "createIntent": "const { data: intent } = await wf.unwrap(\n wf.raw.createIntent({\n body: {\n action_name: \"syndicates.close_deal\",\n resource_type: \"Club\",\n resource_id: \"syn_example\",\n params: { fundraise_id: 99 },\n // Safe to retry: an existing pending/executed intent with this key is returned instead.\n idempotency_key: \"close-acme-series-a\",\n requested_by_agent: \"My Deal Bot\",\n },\n }),\n);\n// Hand this URL to a human — the action executes only after they approve.\nconsole.log(intent?.attributes?.review_url);",
12
12
  "createWebhookEndpoint": "const endpoint = await wf.webhookEndpoints.create({\n url: \"https://yourapp.com/webhooks/wefunder\", // public HTTPS (localhost/private IPs rejected)\n events: [\"offering.opened\", \"investment.executed\", \"investment.changed\"],\n mode: \"live\",\n});\n// Store this now — it's needed by constructEvent() and is never shown again.\nconst signingSecret = endpoint.attributes?.secret;\nconsole.log(endpoint.id, signingSecret);",
13
13
  "createWebhookSubscription": "const subscription = await wf.unwrap(\n wf.raw.createWebhookSubscription({\n path: { campaign_id: 1234 },\n body: {\n target_url: \"https://example.com/wefunder/webhooks\",\n events: [\"investment.confirmed\", \"investment.canceled\"],\n },\n }),\n);\nconsole.log(subscription);",
@@ -21,18 +21,18 @@
21
21
  "getCompanyPitch": "const { data: pitch } = await wf.unwrap(\n wf.raw.getCompanyPitch({ path: { id: \"co_abc123Example\" }, query: { sections: [\"story\", \"perks\"] } }),\n);\nconsole.log(pitch?.attributes);",
22
22
  "getCompanyUpdate": "const { data: update } = await wf.unwrap(\n wf.raw.getCompanyUpdate({ path: { id: \"co_abc123Example\", update_id: \"upd_9t2xExample\" } }),\n);\nconsole.log(update?.attributes?.title);",
23
23
  "getCurrentUser": "const me = await wf.users.me();\nconsole.log(\"Logged in as\", me.id);",
24
- "getInstallation": "const { data: install } = await wf.unwrap(wf.raw.getInstallation({ path: { external_id: \"ins_9t2xExample\" } }));\nconsole.log(install?.attributes);",
24
+ "getInstallation": "const install = await wf.installations.get(\"ins_9t2xExample\");\nconsole.log(install.attributes);",
25
25
  "getIntent": "const intent = await wf.intents.get(\"intent_abc123\");\nconsole.log(intent.attributes?.status); // pending | approved | executed | expired | rejected | failed",
26
26
  "getInvestment": "const investment = await wf.investments.get(\"inv_8f3kQ2Example\");\nconsole.log(investment.status, investment.amounts?.committed_cents, investment.investor?.id);",
27
27
  "getOffering": "const offering = await wf.offerings.get(\"ofr_QfmTyP8qjfYAvkEgREyL3kLf\");\nconsole.log(offering.attributes?.company_name, offering.attributes?.status);",
28
- "getOfferingStats": "const { data: stats } = await wf.unwrap(\n wf.raw.getOfferingStats({ path: { offering_id: \"ofr_QfmTyP8qjfYAvkEgREyL3kLf\" } }),\n);\nconsole.log(stats);",
28
+ "getOfferingStats": "const stats = await wf.offerings.stats(\"ofr_QfmTyP8qjfYAvkEgREyL3kLf\");\nconsole.log(stats.total?.count, stats.total?.raised_cents, stats.by_status);",
29
29
  "getPortfolio": "const summary = await wf.portfolio.get();\nconsole.log(\n summary.attributes?.total_current_value_cents,\n summary.attributes?.return_multiple,\n);",
30
30
  "getSyndicate": "const syndicate = await wf.syndicates.get(42);\nconsole.log(syndicate.attributes?.name, syndicate.attributes?.deal_count);",
31
31
  "getSyndicatePortfolio": "const { data: summary } = await wf.unwrap(\n wf.raw.getSyndicatePortfolio({\n path: { syndicate_id: \"syn_example\" },\n }),\n);\nconsole.log(summary?.attributes?.total_current_value_cents);",
32
32
  "getWebhookEndpoint": "const endpoint = await wf.webhookEndpoints.get(\"whe_8f3ExampleEndpoint00\");\nconsole.log(endpoint.attributes?.events, endpoint.attributes?.failing_since);",
33
33
  "getWebhookSubscription": "const subscription = await wf.unwrap(\n wf.raw.getWebhookSubscription({ path: { campaign_id: 1234, webhook_id: 56 } }),\n);\nconsole.log(subscription.data);",
34
34
  "guides/client-credentials": "const wf = await Wefunder.fromClientCredentials({\n clientId: process.env.WEFUNDER_CLIENT_ID!,\n clientSecret: process.env.WEFUNDER_CLIENT_SECRET!,\n scopes: [\"read:public\"],\n});\n\nconsole.log(\"mode:\", wf.mode); // \"live\" or \"test\", from the token prefix\n\n// client_credentials holds only read:public — browse public offerings.\n// (wf.users.me() would throw 403 insufficient_scope: it needs read:profile.)\nfor await (const offering of wf.offerings.all()) {\n console.log(offering.id);\n}",
35
- "guides/install-target": "// 1. Which companies / syndicates may this user install on? (Only those — an investor's\n// empty list is not a failure.)\nconst targets = await wf.unwrap(\n wf.raw.listEligibleInstallTargets({ query: { target_type: \"syndicate\" } }),\n);\nfor (const t of targets.data ?? [])\n console.log(t.id, t.name, t.installed ? \"(already installed)\" : \"\");\n\n// 2. Install. The response carries the install (`data`) AND its token. If the app is\n// already installed here the API answers 409 `already_installed` — its `details.installation`\n// is the existing install's id, so mint a fresh token for that instead. Any other error\n// (revoked install, missing scope) still throws.\nlet installationToken: string | undefined;\ntry {\n const installed = await wf.unwrap(\n wf.raw.createInstallation({\n body: {\n target_type: \"syndicate\",\n target_id: syndicateId,\n scopes: [\"read:syndicates\"],\n },\n }),\n );\n installationToken = installed.token?.access_token;\n} catch (err) {\n if (!(err instanceof WefunderError) || err.type !== \"already_installed\")\n throw err;\n const existingId = (err.details as { installation?: string } | undefined)\n ?.installation;\n if (!existingId) throw err;\n const minted = await wf.unwrap(\n wf.raw.createInstallationToken({ path: { external_id: existingId } }),\n );\n installationToken = minted.token?.access_token; // shown once — store it\n}\nif (!installationToken) throw new Error(\"no installation token returned\");\n\n// 3. First request AS the installation.\nconst asSyndicate = new Wefunder({ accessToken: installationToken });\nconst deals = await asSyndicate.unwrap(\n asSyndicate.raw.listSyndicateDeals({ path: { syndicate_id: syndicateId } }),\n);\nconsole.log(deals.data?.length, \"deals\");",
35
+ "guides/install-target": "// 1. Which companies / syndicates may this user install on? (Only those — an investor's\n// empty list is not a failure.)\nconst targets = await wf.installations.eligibleTargets({\n target_type: \"syndicate\",\n});\nfor (const t of targets)\n console.log(t.id, t.name, t.installed ? \"(already installed)\" : \"\");\n\n// 2. Install. The response carries the install (`data`) AND its token. If the app is\n// already installed here the API answers 409 `already_installed`; installOrMintToken\n// mints a fresh token for that existing install instead, re-requesting the same scopes.\n// Any other error (revoked install, missing scope) still throws.\nconst installed = await wf.installations.installOrMintToken({\n target_type: \"syndicate\",\n target_id: syndicateId,\n scopes: [\"read:syndicates\"],\n});\nconst installationToken = installed.token?.access_token; // shown once — store it\nif (!installationToken) throw new Error(\"no installation token returned\");\n\n// 3. First request AS the installation.\nconst asSyndicate = new Wefunder({ accessToken: installationToken });\nconst deals = await asSyndicate.unwrap(\n asSyndicate.raw.listSyndicateDeals({ path: { syndicate_id: syndicateId } }),\n);\nconsole.log(deals.data?.length, \"deals\");",
36
36
  "guides/user-token": "// 1. Send the investor to consent. Keep state + the PKCE verifier in their session.\nconst pkce = generatePkce();\nconst state = crypto.randomUUID();\nawait saveAttempt(state, pkce.codeVerifier);\nconst authorizationUrl = createAuthorizationUrl({\n clientId: process.env.WEFUNDER_CLIENT_ID!,\n redirectUri: process.env.WEFUNDER_REDIRECT_URI!,\n scopes: [\"read:investments\"],\n state,\n pkce,\n});\n// redirect(authorizationUrl)\n\n// 2. On the callback, exchange the code (after checking `state` matches the session).\nconst tokens = await exchangeCode({\n clientId: process.env.WEFUNDER_CLIENT_ID!,\n clientSecret: process.env.WEFUNDER_CLIENT_SECRET, // omit for public clients\n code: \"AUTHORIZATION_CODE\",\n redirectUri: process.env.WEFUNDER_REDIRECT_URI!,\n codeVerifier: pkce.codeVerifier,\n});\n\n// 3. Read their holdings. The access token lasts two hours; the SDK rotates the refresh\n// token for you and hands every new set to `store.save` — persist the whole thing.\nconst wf = new Wefunder({\n tokens,\n clientId: process.env.WEFUNDER_CLIENT_ID!,\n clientSecret: process.env.WEFUNDER_CLIENT_SECRET,\n store: { save: (next: TokenSet) => persistTokens(next) },\n});\nconst portfolio = await wf.portfolio.get();\nconsole.log(portfolio.attributes?.total_current_value_cents);",
37
37
  "listActivity": "// Everything my connected apps did to syndicate members, most recent first.\nconst activity = await wf.unwrap(\n wf.raw.listActivity({\n query: { action_pattern: \"syndicates.member.*\", status: \"success\" },\n }),\n);\nfor (const event of activity.data ?? []) {\n console.log(event.attributes?.action, event.attributes?.created_at);\n}",
38
38
  "listAttributedInvestments": "const investments = await wf.unwrap(\n wf.raw.listAttributedInvestments({\n path: { campaign_id: 1234 },\n query: { start_date: \"2026-01-01\", detail_level: \"anonymized\" },\n }),\n);\nfor (const investment of investments.data ?? []) {\n if (\"amount_tier\" in investment) {\n // Anonymized row: opaque tokens + an amount tier, never exact values or PII.\n console.log(investment.investor_token, investment.amount_tier, investment.attribution?.utm_source);\n }\n}",
@@ -42,9 +42,9 @@
42
42
  "listCompanyQuestions": "const page = await wf.unwrap(\n wf.raw.listCompanyQuestions({\n path: { id: \"co_abc123Example\" },\n query: { q: \"revenue\", unanswered_by_team: true, per_page: 20 },\n }),\n);\nfor (const question of page.data ?? []) console.log(question.id, question.attributes);",
43
43
  "listCompanyUpdates": "const page = await wf.unwrap(wf.raw.listCompanyUpdates({ path: { id: \"co_abc123Example\" }, query: { per_page: 10 } }));\nfor (const update of page.data ?? []) console.log(update.id, update.attributes?.title);\nconsole.log(page.meta?.next_cursor);",
44
44
  "listConnectedApps": "const apps = await wf.unwrap(wf.raw.listConnectedApps());\nfor (const app of apps.data ?? []) {\n console.log(app.id, app.attributes?.name);\n}",
45
- "listEligibleInstallTargets": "const targets = await wf.unwrap(wf.raw.listEligibleInstallTargets({ query: { target_type: \"company\" } }));\nfor (const target of targets.data ?? []) console.log(target);",
45
+ "listEligibleInstallTargets": "const targets = await wf.installations.eligibleTargets({\n target_type: \"company\",\n});\nfor (const target of targets)\n console.log(target.id, target.name, target.tier, target.installed);",
46
46
  "listFollowedCompanies": "const page = await wf.unwrap(wf.raw.listFollowedCompanies({ query: { per_page: 25 } }));\nfor (const company of page.data ?? []) console.log(company.id);",
47
- "listInstallations": "const installs = await wf.unwrap(wf.raw.listInstallations());\nfor (const install of installs.data ?? []) console.log(install.id, install.attributes);",
47
+ "listInstallations": "const installs = await wf.installations.list();\nfor (const install of installs.data ?? [])\n console.log(install.id, install.attributes);",
48
48
  "listIntents": "// Which of my proposed actions are still waiting on human approval?\nconst page = await wf.intents.list({ status: \"pending\" });\nfor (const intent of page.data ?? []) {\n console.log(intent.id, intent.attributes?.action, intent.attributes?.review_url);\n}",
49
49
  "listInvestments": "// Auto-paginate the full history lazily:\nfor await (const investment of wf.investments.all()) {\n console.log(investment.id);\n}\n\n// Or grab one page with its meta (next_cursor, etc.):\nconst page = await wf.investments.list();\nconsole.log(page.data?.length, page.meta?.next_cursor);",
50
50
  "listMyCompanies": "const companies = await wf.unwrap(wf.raw.listMyCompanies());\nfor (const company of companies.data ?? []) console.log(company.id, company.attributes?.name);",
@@ -56,7 +56,7 @@
56
56
  "listWebhookSubscriptions": "const subscriptions = await wf.unwrap(\n wf.raw.listWebhookSubscriptions({ path: { campaign_id: 1234 } }),\n);\nfor (const sub of subscriptions.data ?? []) {\n console.log(sub.id, sub.target_url, sub.events, sub.active);\n}",
57
57
  "previewIntent": "const preview = await wf.unwrap(\n wf.raw.previewIntent({\n body: {\n action_name: \"syndicates.close_deal\",\n resource_type: \"Club\",\n resource_id: \"syn_example\",\n params: { fundraise_id: 99 },\n },\n }),\n);\nconsole.log(preview);",
58
58
  "reenableWebhookEndpoint": "const endpoint = await wf.webhookEndpoints.reenable(\"whe_8f3ExampleEndpoint00\");\nconsole.log(endpoint.attributes?.enabled); // true",
59
- "revokeInstallation": "const result = await wf.unwrap(wf.raw.revokeInstallation({ path: { external_id: \"ins_9t2xExample\" } }));\nconsole.log(result);",
59
+ "revokeInstallation": "const revoked = await wf.installations.revoke(\"ins_9t2xExample\");\nconsole.log(revoked.attributes?.status); // \"revoked\"",
60
60
  "rotateWebhookEndpointSecret": "const endpoint = await wf.webhookEndpoints.rotateSecret(\"whe_8f3ExampleEndpoint00\");\nconst newSecret = endpoint.attributes?.secret; // shown once\nconsole.log(newSecret);",
61
61
  "searchCompanies": "const results = await wf.unwrap(wf.raw.searchCompanies({ query: { q: \"solar\", limit: 5 } }));\nfor (const hit of results.data ?? []) console.log(hit.id, hit.attributes?.name);",
62
62
  "testWebhookEndpoint": "const outcome = await wf.webhookEndpoints.test(\"whe_8f3ExampleEndpoint00\", \"investment.executed\");\nif (outcome.delivered) {\n console.log(`endpoint answered ${outcome.response_code} in ${outcome.duration_ms}ms`);\n} else {\n console.log(`no response: ${outcome.error}`); // timeout | blocked_url | tls_error | connection_failed\n}",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wefunder/sdk",
3
- "version": "0.1.0-beta.10",
3
+ "version": "0.1.0-beta.12",
4
4
  "description": "Official TypeScript SDK for the Wefunder API (beta)",
5
5
  "license": "MIT",
6
6
  "type": "module",