Skip to main content

Syndicate Deals

A deal is a round (offering) the syndicate is raising for. Reads need read:syndicates. Deals are addressed by their ofr_ offering id, the same id the Explore API uses.

Monetary values

amount_raised, min_investment, and max_investment are whole US dollars as strings ("230000" is $230,000). funding_target is cents as a string ("50000000" is $500,000.00).

List deals​

GET /syndicates/:id/deals

Returns the syndicate's live deals: the rounds in the visible set that are open, oversubscribed, or closing. Closed and upcoming rounds are not listed. Cursor-paginated; per_page defaults to 25 and caps at 100.

Which rounds are deals​

The API builds the syndicate's deal set from how the syndicate links to its companies, and the set is narrower than "every round the syndicate has ever been linked to":

  • Syndicates with companies in their directory (the usual case): every round of every company in the directory, except rounds of a company that is invite-only and except testing-the-waters rounds.
  • Syndicates with no directory companies, whose deals are linked round by round: every linked round, except rounds of an invite-only company. Testing-the-waters rounds are not excluded on this path.

This visible set is what total_deals in statistics counts; its live subset is what this endpoint lists, what live_deals counts, and what deal_count on the syndicate reports. A round a manager can see on Wefunder but that falls outside the set (an invite-only company's round, or a testing-the-waters round of a directory company) does not appear here and is not counted.

curl "https://api.wefunder.com/syndicates/syn_aB3xQ9k2vF8mNp1zT5wY7Qc4/deals" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{
"data": [
{
"id": "ofr_kUlkWcWVugo7cSLD4RdD6gdK",
"type": "syndicate_deal",
"attributes": {
"name": "Acme Corp Series A",
"status": "open",
"company_name": "Acme Corp",
"company_id": 789,
"company": "co_siInncsiLN5KkUAXVRTpqMBi",
"company_url": "https://wefunder.com/acmecorp",
"company_logo_url": "https://uploads.wefunder.com/uploads/company/logo/789/acme.png",
"amount_raised": "230000",
"investor_count": 47,
"funding_target": "50000000",
"exemption": { "family": "reg_d", "subtype": "506c", "label": "Reg D 506(c)" },
"security": {
"type": "safe",
"label": "SAFE",
"terms": {
"valuation_cap": "20000000",
"uncapped": false,
"discount_percent": "20",
"most_favored_nation": false,
"pro_rata": true
}
},
"min_investment": "1000",
"max_investment": null,
"description": "Acme Corp is building next-gen widgets for the enterprise market.",
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-03-01T14:00:00Z",
"closed_at": null,
"funding_started_at": "2026-01-15T10:00:00Z"
}
}
],
"meta": {
"has_more": false,
"page_count": 1
}
}

Fields​

FieldNotes
statusupcoming, open, closed, or canceled. Live deals are always open
amount_raised, investor_countActive, non-hellbanned platform investments only. The same filters the syndicate's statistics use
exemptionfamily is reg_cf, reg_a, reg_d, reg_s, or ecsp; subtype is 506b or 506c for Reg D, otherwise null. Null if the round has no exemption on file
securityWhat the round issues, keyed by type (safe, equity, convertible_note, revenue_share, debt, fund, other), with a terms object whose shape depends on the type. Null for a round with no final terms. See the Security schema in the API reference
descriptionThe round's stated use of funds
company_idDeprecated integer; use company (co_)

Get a deal​

GET /syndicates/:id/deals/:fundraise_id

Same representation as the list. 404 if the offering is not one of this syndicate's deals.

Draft a deal (preview)​

Preview

Drafting is in preview and enabled per syndicate. It may change without a new API version. Ask your Wefunder contact to turn it on. Until it is on for your syndicate, these requests return 404.

Would you build on this? Tell us, and it helps decide what opens up next.

A manager can draft an SPV deal through the API, up to the point where it is ready to sign and open on wefunder.com. No API call opens a deal: signing the listing agreement (and the tax service agreement, when the vehicle needs one) and opening the deal happen on the website.

POST /syndicates/:id/deals

Requires write:syndicates and a user token for a manager or operator of the syndicate; that person becomes the deal's lead. The body goes under deal; every field is described in Creating SPVs. It replaces the removed POST /partner/spvs, which took the same fields.

curl -X POST "https://api.wefunder.com/syndicates/syn_aB3xQ9k2vF8mNp1zT5wY7Qc4/deals" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Idempotency-Key: 7f9c2e1a-deal-acme" \
-H "Content-Type: application/json" \
-d '{
"deal": {
"name": "Acme SPV",
"series_name": "Acme Series 2026",
"target_company_id": "co_8Kd0aB3xQ9k2vF8mNp1zT5wY",
"terms": {
"structure": "safe",
"valuation_cap_cents": 1000000000,
"minimum_investment_cents": 100000,
"max_raise_cents": 50000000
},
"settings": { "accreditation_type": "verified" }
}
}'

Response (201): the deal, in upcoming status, plus meta.target_company. The deal is not shown to the syndicate's members and does not appear in GET /syndicates/:id/deals while it is a draft.

StatusWhen
200Replay of an earlier create with the same Idempotency-Key
403Not a manager or operator, a syndicate-owned token (user_principal_required), or a token without write:syndicates
404target_company_id not found, or no company matches the name. Only companies you can see on wefunder.com, companies you manage, and companies already in the syndicate's pipeline are matched; any other company is reported exactly as if it did not exist
409The name matches more than one company; resubmit with one of details.candidates
422Invalid terms, or a syndicate whose members join through a fund (unsupported_syndicate_type)

settings.accreditation_type: "verified" makes the deal a 506(c) offering; otherwise it is 506(b).

Readiness​

Preview

Readiness is a preview endpoint. It isn't in the public API reference yet.

GET /syndicates/:id/deals/:fundraise_id/readiness

Lists what stands between the deal and signing and opening it on wefunder.com, in the order the setup wizard asks. Each item's status is complete, missing, needs_human, needs_staff or blocked; action_url, when present, is the wefunder.com page for that step.

{
"data": {
"id": "ofr_kUlkWcWVugo7cSLD4RdD6gdK",
"type": "syndicate_deal_readiness",
"attributes": {
"ready": false,
"status": "upcoming",
"items": [
{ "key": "target_company", "label": "Company the SPV invests in", "status": "complete", "detail": null, "action_url": null, "blocked_by": [] },
{ "key": "allocation", "label": "Amount the SPV invests in the company", "status": "missing", "detail": "Set an allocation of at least $1,000. Not yet settable through the API.", "action_url": null, "blocked_by": [] },
{ "key": "sign_and_open", "label": "Sign the listing and tax service agreements and open the deal on wefunder.com", "status": "blocked", "detail": "Complete the items above first.", "action_url": null, "blocked_by": ["allocation"] }
]
}
}
}

The items are target_company, terms, allocation, series, master_llc, advisor, conflict_disclosures, carry_agreements and sign_and_open (abridged above). Managers and operators only.

Deal investors​

GET /syndicates/:id/deals/:fundraise_id/investors

One row per syndicate member who invested in the deal, aggregated across their investments in it, largest total first. Members who have resigned or been exiled are excluded.

Managers and operators only. Who invested how much is moderator data, the same rule as the web deal pipeline page and GET /syndicates/:id/members/:member_id/investments: a token acting for an ordinary member, backer, or follower gets 403 even though it holds read:syndicates. Callers who pass that gate see user_email.

curl "https://api.wefunder.com/syndicates/syn_aB3xQ9k2vF8mNp1zT5wY7Qc4/deals/ofr_kUlkWcWVugo7cSLD4RdD6gdK/investors?per_page=50" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{
"data": [
{
"id": "usr_2mNp1zT5wY7Qc4aB3xQ9k2vF",
"type": "deal_investor",
"attributes": {
"user_id": 456,
"user": "usr_2mNp1zT5wY7Qc4aB3xQ9k2vF",
"user_name": "Jane Smith",
"user_email": "[email protected]",
"avatar_url": "https://uploads.wefunder.com/uploads/user/avatar/456/jane.jpg",
"amount": "15000",
"status": "confirmed",
"invested_at": "2026-01-20T14:30:00Z"
}
}
],
"meta": {
"count": 1,
"total_count": 1,
"offset": 0,
"per_page": 50,
"has_more": false
}
}

The row's id is the investor's usr_ id. amount is whole dollars; status is the investor's most advanced commitment, pending or confirmed; invested_at is their most recent investment in the deal.

ParamDescription
per_pageRows per page, up to 200. Omit for all rows
offsetRows to skip
user_email is always present

The endpoint is manager/operator only, so every caller who gets a 200 sees the email. An ordinary member, backer, or follower gets 403 for the whole request rather than a redacted row.

Close and finalize (2026-10-01 only)​

Removed in 2026-10-15

These two endpoints are not part of Wefunder-Version: 2026-10-15 or later; they return 404 not_found with removed_in_version: "2026-10-15". Applications pinned to 2026-10-01 keep them, unchanged. A syndicate's managers close and finalize deals on wefunder.com.

Closing and finalizing a deal are irreversible, so neither happens on the request. Each endpoint records a pending intent and returns the URL where a human approves it. The deal changes only when a user with full_access approves on Wefunder.

Proposing requires write:syndicates and full_access standing; operators get 403.

POST /syndicates/:id/deals/:fundraise_id/close
POST /syndicates/:id/deals/:fundraise_id/finalize
curl -X POST "https://api.wefunder.com/syndicates/syn_aB3xQ9k2vF8mNp1zT5wY7Qc4/deals/ofr_kUlkWcWVugo7cSLD4RdD6gdK/close" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response (200):

{
"data": { "id": "ofr_kUlkWcWVugo7cSLD4RdD6gdK", "type": "syndicate_deal", "attributes": { "...": "..." } },
"meta": {
"close_deal_intent": {
"id": "int_aB3xQ9k2vF8mNp1zT5wY7Qc4",
"status": "pending",
"review_url": "https://wefunder.com/intents/12345/review"
}
}
}

finalize returns the same shape under meta.finalize_deal_intent. Repeating the call while an intent for that deal is still pending returns the existing intent rather than creating another. Poll GET /intents/:id to see when it is approved and executed.

StatusWhen
403Caller lacks full_access
422The deal does not belong to this syndicate
429Too many pending intents for this token
Was this page helpful?