Activity & Audit Trail
Every action an application takes through the API on a user's behalf is recorded and visible to that user. Someone who connects an agent to their syndicate can see exactly what it read, what it changed, and what it proposed.
What the user sees
In their Wefunder account settings a user can review the apps they have connected and a feed of what each one did:
Today
Claude via Wefunder MCP
2:45 PM Invited [email protected] to Acme Syndicate
2:30 PM Proposed: remove Bob Smith from Acme Syndicate — pending your approval
2:28 PM Viewed member directory
Yesterday
CRM Sync
4:12 PM Exported member CSV
They can revoke any app from the same place. Design your integration knowing the user is watching.
Activity API
GET /activity is not part of Wefunder-Version: 2026-10-15 or later; it returns 404 not_found with removed_in_version: "2026-10-15". Applications pinned to 2026-10-01 keep it, unchanged. The /activity name is reserved for the activity feed. The user can still see every action an app took in Settings → Activity on wefunder.com.
On 2026-10-01, the same feed is available to your application for the user who authorized it.
List activity
GET /activity
Requires read:profile. Returns audit events for apps this user has authorized, newest first.
curl "https://api.wefunder.com/activity?since=2026-03-01T00:00:00Z&action_pattern=syndicates.*" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{
"data": [
{
"id": "12345",
"type": "audit_event",
"attributes": {
"occurred_at": "2026-03-05T14:45:00Z",
"actor_type": "agent",
"actor_name": "Claude via Wefunder MCP",
"action": "syndicates.member.invited",
"resource_type": "Club",
"resource_id": "syn_aB3xQ9k2vF8mNp1zT5wY7Qc4",
"resource_label": "Acme Syndicate",
"old_values": null,
"new_values": { "email": "[email protected]", "invite_role": "member" },
"changed_fields": ["email", "invite_role"],
"status": "success",
"error_message": null,
"intent": null,
"created_at": "2026-03-05T14:45:00Z"
}
}
],
"meta": { "has_more": true, "page_count": 25, "next_cursor": "2026-03-05T14:45:00.000000Z" }
}
intent carries the int_... id when the event was the proposal or execution of an intent. status is success, failure, or denied; denied records an attempt the API refused, which is useful when debugging a misbehaving agent.
Filters
| Param | Description |
|---|---|
app_id | Only events by one connected app |
action_pattern | Prefix match on the action name, e.g. syndicates.* or syndicates.member.* |
resource_type + resource_id | Only events on one resource; both are required together. For syndicates pass Club and the syn_... id |
status | success, failure, or denied |
since / until | ISO 8601 bounds on occurred_at |
Pagination is by timestamp cursor; pass meta.next_cursor back as cursor. See Pagination.
Connected apps
GET /connected-apps
Requires read:profile. Lists the applications this user has authorized, with their granted scopes, last activity, and action count.
DELETE /connected-apps/{app_id}
Requires write:profile. Revokes every token the app holds for this user and returns { "data": { "revoked": true, "tokens_revoked": 2 } }. Revocation is recorded as an activity event.
What is recorded
| Example | |
|---|---|
| What | syndicates.member.invited |
| Who | Claude via Wefunder MCP |
| On behalf of | the user who authorized the app |
| Resource | Acme Syndicate (syn_aB3xQ9k2vF8mNp1zT5wY7Qc4) |
| When | 2026-03-05 14:45:00 UTC |
| Changes | email, invite_role |
| Outcome | success, failure, or denied |
Agent and human actions are distinguished: "Greg invited [email protected]" versus "Claude (authorized by Greg) invited [email protected]". The delegation chain, which person authorized which app to take which action, is always visible.
Why this matters
Agents managing money and investor relationships are only acceptable if the people responsible can see everything the agent did, revoke it instantly, and know that the dangerous actions waited for their approval. The activity feed, connected-apps revocation, and intents are the three parts of that promise.