Intents

Propose an intent

Changed on

Propose a dangerous or irreversible action for human approval. Returns a review_url where a human must review the impact and approve before the action executes.

The entity that proposes an intent can never approve it. Approval always happens on Wefunder's UI by a user with permission on the resource.

Each action names the scope that may propose it and the resource type it targets (syndicates.* → write:syndicates on a syndicate; comments.create → write:comments on a Company). The token must hold that action's scope; holding another proposing scope is not enough (403 insufficient_scope).

comments.create posts a question on a company's Ask tab, or an answer to one, as the requesting user once they approve on wefunder.com. resource_id is the company (co_...); params is { target_type: "company" | "comment", target: "co_..." | "cmt_...", body, disclosure_key? } (disclosure_key ∈ investor, stockholder, promoter, financial_stakeholder). Who may post is the site's own rule: anyone the page is available to may ask (unless the company has closed questions); only the company's team may answer. Only the requester can approve. 20 proposals per user per day (429).

An idempotency_key names one operation. Reusing it for the same operation returns the existing intent (200) while that intent is pending, approved, executing, or executed; reusing it for a different action, resource, or params is a 409 idempotency_conflict.

An action still rolling out per account returns 403 feature_disabled for a user who is not yet enabled. POST /intents/preview runs the same checks without minting.

See Intents documentation for the full pattern.

post/intents

Request

  • Base URL: https://api.wefunder.com
  • URL: https://api.wefunder.com/intents
  • Auth: one of:
    • OAuth 2 (authorization code, authorization URL https://wefunder.com/oauth/authorize, token URL https://api.wefunder.com/oauth/token; client credentials, token URL https://api.wefunder.com/oauth/token, scopes: write:syndicates)
    • OAuth 2 (authorization code, authorization URL https://wefunder.com/oauth/authorize, token URL https://api.wefunder.com/oauth/token; client credentials, token URL https://api.wefunder.com/oauth/token, scopes: write:comments)

Request body

action_name'syndicates.close_deal' | 'syndicates.finalize_deal' | 'syndicates.publish' | 'syndicates.remove_member' | 'syndicates.delete_draft' | 'comments.create' required

The action to perform

resource_typestring required

The resource type the action targets, as the action table names it; the example is the syndicate type.

resource_idstring required

The resource's id in the API's vocabulary — the syndicate's syn_... for a syndicates.* action.

paramsobject

Action-specific parameters

idempotency_keystring

Client-provided key naming this one operation. While an intent with this key is pending, approved, executing, or executed, the same operation returns it (200); a different operation under the same key is a 409.

requested_by_agentstring

Human-readable name of the agent proposing the action

Example request

{
  "action_name": "syndicates.close_deal",
  "resource_type": "Club",
  "resource_id": "syn_aB3xQ9k2vF8mNp1zT5wY7Qc4",
  "params": {
    "fundraise_id": 99
  },
  "idempotency_key": "close-acme-series-a",
  "requested_by_agent": "Claude via MCP"
}

Response

Idempotent replay — the existing intent for this key and operation.

Example response

{
  "data": {
    "id": "int_aB3xQ9k2vF8mNp1zT5wY7Qc4",
    "type": "intent",
    "attributes": {
      "action": "syndicates.close_deal",
      "status": "pending",
      "resource_type": "Club",
      "impact_summary": "Close the Acme Corp Series A deal. 47 investors have committed $2.3M.",
      "review_url": "https://wefunder.com/intents/a1b2c3d4-e5f6-7890-abcd-ef1234567890/review",
      "requested_by_agent": "Claude via MCP",
      "expires_at": "2025-03-01T12:00:00Z",
      "approved_at": "2025-03-01T12:00:00Z",
      "executed_at": "2025-03-01T12:00:00Z",
      "rejection_reason": "Example text",
      "created_at": "2025-03-01T12:00:00Z",
      "updated_at": "2025-03-01T12:00:00Z"
    }
  }
}

Changes

    • breaking

      the response property // became nullable for the status

    • breaking

      response property data/attributes/resource_id list-of-types was widened by adding types integer to media type application/json of response 201

    • breaking

      the / response's property format changed from uuid to no format for status

    • warning

      removed the optional property from the response with the status

    • info

      added the new comments.create enum value to the request property

    • info

      added the optional property to the response with the status

    • info

      added the success response with the status

    • breaking

      the request property type changed from integer to string

    • breaking

      the // response's property type changed from integer to string for status

    • breaking

      the // response's property type changed from integer to string for status