Wefunder Syndicate Members API
The Syndicate Members API from Wefunder — 12 operation(s) for syndicate members.
The Syndicate Members API from Wefunder — 12 operation(s) for syndicate members.
openapi: 3.0.1
info:
title: Wefunder API v2 Activity Syndicate Members API
description: 'OAuth 2.0 API for accessing Wefunder data programmatically.
## Authentication
This API uses OAuth 2.0 for authentication. To get started:
1. Create an OAuth application at `/oauth/applications`
2. Get your Client ID and Client Secret
3. Implement the OAuth 2.0 Authorization Code flow
4. Use the access token to make API requests
## Rate Limits
- Standard API: 1,000 requests/hour per token
- Admin API: 10,000 requests/hour per token
## Base URL
All API requests should be made to: `https://api.wefunder.com/api/v2`
'
version: '2.0'
contact:
name: Wefunder API Support
email: api@wefunder.com
servers:
- url: https://{environment}.wefunder.com/api/v2
variables:
environment:
default: api
enum:
- api
- staging
tags:
- name: Syndicate Members
paths:
/syndicates/{syndicate_id}/members:
get:
tags:
- Syndicate Members
summary: List members
description: 'Returns the member directory for a syndicate with role, status, tags, sidebar notes,
and investment history summaries. Supports filtering, sorting, search, and pagination.
'
operationId: listSyndicateMembers
security:
- bearerAuth:
- read:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
- name: role
in: query
schema:
type: string
description: Filter by role (e.g. creator, manager, member, invitee, applicant)
- name: permission
in: query
schema:
type: string
enum:
- full_access
- operator
description: Filter by syndicate permission level
- name: search
in: query
schema:
type: string
description: Search by name or email
- name: sort
in: query
schema:
type: string
enum:
- relevance
- newest
- oldest
- alphabetical
- last_activity
description: Sort order for results
- name: has_invested
in: query
schema:
type: string
enum:
- 'true'
- 'false'
description: Filter by whether the member has invested in any syndicate deal
- name: accredited
in: query
schema:
type: string
enum:
- 'true'
description: Filter to accredited members only
- name: tag
in: query
schema:
type: string
description: Filter by 'can help with' tag (ILIKE match)
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/SyndicateMemberListEnvelope'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/syndicates/{syndicate_id}/members/invite:
post:
tags:
- Syndicate Members
summary: Invite member
description: Send an invitation to join the syndicate by email.
operationId: inviteSyndicateMember
security:
- bearerAuth:
- write:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email
properties:
email:
type: string
format: email
example: jane@example.com
name:
type: string
description: Display name for the invitee
syndicate_permission:
type: string
enum:
- full_access
- operator
default: operator
description: Permission level. Only the syndicate creator can assign full_access (admin).
responses:
'201':
description: Invitation sent
content:
application/json:
schema:
$ref: '#/components/schemas/SyndicateMemberEnvelope'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
description: Validation error (e.g. already a member)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/syndicates/{syndicate_id}/members/{member_id}:
patch:
tags:
- Syndicate Members
summary: Update member
description: Update title and carry override for a member. Requires operator permission.
operationId: updateSyndicateMember
security:
- bearerAuth:
- write:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
- $ref: '#/components/parameters/member_id'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- member
properties:
member:
type: object
properties:
title:
type: string
example: Lead Investor
carry_percentage_override:
type: string
example: '20.0'
responses:
'200':
description: Member updated
content:
application/json:
schema:
$ref: '#/components/schemas/SyndicateMemberEnvelope'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
delete:
tags:
- Syndicate Members
summary: Remove member (requires intent)
description: 'Removing a member is irreversible and requires human approval through the Intent system.
This endpoint always returns 422 with a `use_intents` error directing you to
`POST /v2/intents` with action `syndicates.remove_member`.
'
operationId: removeSyndicateMember
security:
- bearerAuth:
- write:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
- $ref: '#/components/parameters/member_id'
responses:
'422':
description: Use intents for this action
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/syndicates/{syndicate_id}/members/{member_id}/approve:
post:
tags:
- Syndicate Members
summary: Approve applicant
description: Approve a pending applicant. Only applicants can be approved via API; invitees must accept their invite link.
operationId: approveSyndicateMember
security:
- bearerAuth:
- write:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
- $ref: '#/components/parameters/member_id'
responses:
'200':
description: Member approved
content:
application/json:
schema:
$ref: '#/components/schemas/SyndicateMemberEnvelope'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/syndicates/{syndicate_id}/members/{member_id}/hide:
post:
tags:
- Syndicate Members
summary: Exile member
description: Exile (hide) a member from the syndicate. Sets their role to exiled.
operationId: hideSyndicateMember
security:
- bearerAuth:
- write:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
- $ref: '#/components/parameters/member_id'
responses:
'200':
description: Member hidden
content:
application/json:
schema:
$ref: '#/components/schemas/SyndicateMemberEnvelope'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/syndicates/{syndicate_id}/members/{member_id}/promote:
post:
tags:
- Syndicate Members
summary: Promote member to admin
description: Promote a member to full_access (admin) role. Only the syndicate creator can promote members.
operationId: promoteSyndicateMember
security:
- bearerAuth:
- write:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
- $ref: '#/components/parameters/member_id'
responses:
'200':
description: Member promoted
content:
application/json:
schema:
$ref: '#/components/schemas/SyndicateMemberEnvelope'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/syndicates/{syndicate_id}/members/{member_id}/demote:
post:
tags:
- Syndicate Members
summary: Demote member to operator
description: Demote a member from full_access (admin) to operator permission.
operationId: demoteSyndicateMember
security:
- bearerAuth:
- write:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
- $ref: '#/components/parameters/member_id'
responses:
'200':
description: Member demoted
content:
application/json:
schema:
$ref: '#/components/schemas/SyndicateMemberEnvelope'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/syndicates/{syndicate_id}/members/{member_id}/restore:
post:
tags:
- Syndicate Members
summary: Restore exiled or resigned member
description: Restore a member who was previously exiled or resigned. Sets their role back to member.
operationId: restoreSyndicateMember
security:
- bearerAuth:
- write:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
- $ref: '#/components/parameters/member_id'
responses:
'200':
description: Member restored
content:
application/json:
schema:
$ref: '#/components/schemas/SyndicateMemberEnvelope'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/syndicates/{syndicate_id}/members/{member_id}/resend_invite:
post:
tags:
- Syndicate Members
summary: Resend invitation
operationId: resendSyndicateInvite
security:
- bearerAuth:
- write:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
- $ref: '#/components/parameters/member_id'
responses:
'200':
description: Invitation resent
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/syndicates/{syndicate_id}/members/reorder:
post:
tags:
- Syndicate Members
summary: Reorder members
description: Set the display order for the member directory.
operationId: reorderSyndicateMembers
security:
- bearerAuth:
- write:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- member_ids
properties:
member_ids:
type: array
items:
type: string
example:
- cr_123
- cr_456
- cr_789
responses:
'200':
description: Order updated
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/syndicates/{syndicate_id}/members/export_csv:
post:
tags:
- Syndicate Members
summary: Export members CSV
description: 'Generate a CSV export of the member directory. Returns the CSV data directly
with Content-Type text/csv. Requires operator permission.
'
operationId: exportSyndicateMembersCsv
security:
- bearerAuth:
- read:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
responses:
'200':
description: CSV data
content:
text/csv:
schema:
type: string
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/syndicates/{syndicate_id}/members/{member_id}/investments:
get:
tags:
- Syndicate Members
summary: List member investments
description: 'Returns this member''s investments in syndicate deals. Scoped to the syndicate''s
selected deals (one per company, matching directory semantics).
All monetary values are strings representing cents to avoid floating-point precision issues.
'
operationId: listSyndicateMemberInvestments
security:
- bearerAuth:
- read:syndicates
parameters:
- $ref: '#/components/parameters/syndicate_id'
- $ref: '#/components/parameters/member_id'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/MemberInvestmentListEnvelope'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
description: Member not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
responses:
Forbidden:
description: 'The authenticated user does not have permission to access this resource.
This typically means:
- The user is authenticated but lacks the required OAuth scope
- The resource belongs to a different user
- The user''s role doesn''t allow this operation
Check that your OAuth token includes the necessary scopes for this endpoint.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: 'Authentication required or token is invalid/expired. This error occurs when:
- No Authorization header is provided
- The access token is invalid or malformed
- The access token has expired
- The access token has been revoked
To resolve: Obtain a new access token using the OAuth 2.0 flow.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
SyndicateMember:
type: object
description: JSON:API resource representing a syndicate member (ClubRole)
properties:
id:
type: integer
example: 123
type:
type: string
example: syndicate_member
attributes:
type: object
properties:
user_id:
type: integer
nullable: true
description: User ID (null for invitees who haven't signed up)
example: 123
user_name:
type: string
nullable: true
example: Jane Smith
user_email:
type: string
nullable: true
description: '**Moderator-only.** User email (or invite_email for pending invitees).
Returns null for non-moderator callers. Requires the requesting user
to be a manager/operator of the syndicate.
'
example: user@example.com
role:
type: string
example: member
description: Current role (creator, manager, member, invitee, applicant, exiled, resigned, etc.)
invite_role:
type: string
nullable: true
description: The role the member was invited as
example: admin
syndicate_permission:
type: string
enum:
- full_access
- operator
description: Permission level within the syndicate
title:
type: string
nullable: true
description: Custom title for the member
example: Example title
sort_order:
type: integer
nullable: true
description: Display order position
example: 5
carry_percentage_override:
type: string
nullable: true
example: '20.0'
description: Override carry percentage for this member
avatar_url:
type: string
nullable: true
description: User profile photo URL (null for invitees without a user account)
example: https://uploads.wefunder.com/uploads/user/avatar/456/large_photo.jpg
bio:
type: string
nullable: true
description: User bio with fallback chain (bio -> thesis -> about). Null for invitees without a user account.
example: Example text
city:
type: string
nullable: true
description: User's city
example: San Francisco
country:
type: string
nullable: true
description: User's country
example: US
last_activity_at:
type: string
format: date-time
nullable: true
description: ISO 8601 timestamp of user's last login. Null for invitees without a user account.
example: '2025-03-01T12:00:00Z'
profile_url:
type: string
nullable: true
description: Relative path to user's profile (e.g. '/janedoe'). Null for invitees without a user account.
example: /janedoe
tags:
type: array
items:
type: string
description: '''Can help with'' tags from the user''s investor profile. Empty array for invitees.'
example:
- Fundraising
- Product Strategy
joined_at:
type: string
format: date-time
description: ISO 8601 join date (alias for created_at)
example: '2025-03-01T12:00:00Z'
investment_total:
type: string
nullable: true
description: Total amount invested in syndicate deals, in cents. String to avoid floating-point precision issues.
example: '500000'
deal_count:
type: integer
nullable: true
description: Number of syndicate deals the member has invested in
example: 2
accredited:
type: boolean
description: '**Moderator-only.** Whether the user is an accredited investor.
Only included when the requesting user is a manager/operator.
'
example: true
legal_name:
type: string
nullable: true
description: '**Moderator-only.** Full legal name of the user.
Only included when the requesting user is a manager/operator.
'
example: Example Name
starred:
type: boolean
description: '**Moderator-only.** Whether the current moderator has starred this member.
Only included when the requesting user is a manager/operator.
'
example: true
private_tags:
type: array
items:
type: string
description: '**Moderator-only.** Labels assigned by moderators via ClubMemberLabel.
Only included when the requesting user is a manager/operator.
'
example:
- VIP
- Follow up
created_at:
type: string
format: date-time
example: '2025-03-01T12:00:00Z'
updated_at:
type: string
format: date-time
example: '2025-03-01T12:00:00Z'
SyndicateMemberListEnvelope:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/SyndicateMember'
meta:
$ref: '#/components/schemas/PaginationMeta'
MemberInvestmentListEnvelope:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/MemberInvestment'
meta:
type: object
properties:
count:
type: integer
description: Number of investments
total_amount:
type: string
description: Sum of all investment amounts in cents, as a string
example: '800000'
PaginationMeta:
type: object
properties:
count:
type: integer
example: 25
has_more:
type: boolean
example: true
next_cursor:
type: integer
nullable: true
example: 12345
SyndicateMemberEnvelope:
type: object
properties:
data:
$ref: '#/components/schemas/SyndicateMember'
Error:
type: object
properties:
error:
type: object
properties:
type:
type: string
example: unauthorized
message:
type: string
example: Invalid or expired token
details:
type: object
additionalProperties: true
request_id:
type: string
description: Unique identifier for this request. Quote it in support tickets.
example: req_abc123
remediation:
type: string
description: When present, a hint on how to resolve the error.
example: Obtain a new access token using the OAuth 2.0 flow.
MemberInvestment:
type: object
description: 'JSON:API resource representing a member''s investment in a syndicate deal.
Scoped to the syndicate''s selected deals (one per company, matching directory semantics).
'
properties:
id:
type: integer
description: Investment ID
example: 789
type:
type: string
example: member_investment
attributes:
type: object
properties:
fundraise_id:
type: integer
description: Deal (fundraise) ID
example: 75496
company_name:
type: string
nullable: true
description: Name of the company the deal is for
example: Substack
amount:
type: string
description: Investment amount in cents, as a string to avoid floating-point precision issues
example: '500000'
state:
type: string
description: Investment state
example: confirmed
created_at:
type: string
format: date-time
description: ISO 8601 timestamp when the investment was created
example: '2025-03-01T12:00:00Z'
parameters:
syndicate_id:
name: syndicate_id
in: path
required: true
description: The syndicate ID
schema:
type: integer
example: 42
member_id:
name: member_id
in: path
required: true
description: The member ID
schema:
type: string
example: cr_123
securitySchemes:
bearerAuth:
type: oauth2
description: OAuth 2.0 authorization with access tokens
flows:
authorizationCode:
authorizationUrl: https://wefunder.com/oauth/authorize
tokenUrl: https://wefunder.com/oauth/token
scopes:
read:public: Read public deal data (explore offerings); requires no user context
read:profile: Read user profile information
read:investments: Read user investment data
read:campaigns: Read campaign information for companies you founded
read:attribution:aggregate: Read aggregate attribution statistics (Tier 0)
read:attribution:anonymized: Read anonymized attribution data (Tier 1 - requires approval)
read:attribution:full: Read full attribution data with investor PII (Tier 2 - founders only)
admin:attribution: Administrative access to attribution system (Tier 3 - Wefunder admins only)
read:syndicates: View syndicates, members, deals, and portfolio
write:syndicates: Manage members, update settings, operate on deals
read:spvs: View partner SPVs, their invites, sessions, and investments
write:spvs: Create and manage partner SPVs, invites, and investment sessions
read:webhooks: View webhook subscriptions
write:webhooks: Create, update, and delete webhook subscriptions
clientCredentials:
tokenUrl: https://wefunder.com/oauth/token
scopes:
read:public: Read public deal data. The only scope a server-side (client_credentials) key may hold — it acts as the app, with no user, so it can never read user-scoped data.