Skip to main content

Crowdfunding

Crowdfunding pools allow pool creators to raise a target amount of capital from contributors before a deadline. Contributors receive pool shares proportional to their contribution. If the target is met, the pool activates and shares are distributed. If the deadline passes without reaching the target, contributors can reclaim their funds.

Crowdfunding endpoints require an API key with the trade scope.

Authentication: X-API-Key header (trade scope)

How Crowdfunding Works

  1. Pool creator sets up a crowdfunding pool with a target amount, deadline, and payment token.
  2. Contributors send payment tokens to the pool during the campaign.
  3. If target is reached before the deadline, the pool finalizes: shares are allocated proportionally, and the pool becomes active for distributions.
  4. If target is not reached by the deadline, the campaign fails: contributors can reclaim their full contribution.
Campaign Created --> Contributors Send Funds --> Deadline Reached
|
+---------+-----------+----------+
| |
Target Met Target Not Met
| |
Pool Activates Funds Returned
Shares Distributed to Contributors

Discover Crowdfunding Pools

Before contributing, find active crowdfunding campaigns using the pool discovery endpoints:

curl "https://home.dobprotocol.com/api/agent/pools/crowdfunding?network_id=10" \
-H "X-API-Key: dob_ak_your_key_here"

See Pools - Active Crowdfunding for full details on the response format.

Prepare Contribution

Prepare an unsigned XDR transaction to contribute to an active crowdfunding pool.

POST /api/agent/crowdfunding/prepare-contribute

Request Body:

FieldTypeRequiredDescription
pool_addressstringYesCrowdfunding pool contract address
amountstringYesContribution amount (decimal string, in payment token units)
network_idintegerYesNetwork ID

curl:

curl -X POST https://home.dobprotocol.com/api/agent/crowdfunding/prepare-contribute \
-H "X-API-Key: dob_ak_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"pool_address": "CA7QYNF7SOVZ4V4LXQHXWJQVGU3ZGR4A5OHCOQZSC7M2XZFKK67TYXZ",
"amount": "500.00",
"network_id": 10
}'

Python:

import requests

resp = requests.post(
"https://home.dobprotocol.com/api/agent/crowdfunding/prepare-contribute",
headers={"X-API-Key": API_KEY},
json={
"pool_address": "CA7QYNF7SOVZ4V4LXQHXWJQVGU3ZGR4A5OHCOQZSC7M2XZFKK67TYXZ",
"amount": "500.00",
"network_id": 10
}
)
data = resp.json()
unsigned_xdr = data["data"]["xdr"]

Response (200 OK):

{
"success": true,
"data": {
"xdr": "AAAAAgAAAABhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0...",
"transaction_details": {
"pool_address": "CA7QYNF7SOVZ4V4LXQHXWJQVGU3ZGR4A5OHCOQZSC7M2XZFKK67TYXZ",
"pool_name": "Wind Turbine Collective",
"amount": "500.00",
"payment_token": "USDC",
"estimated_shares": 625,
"current_raised": "32500.00",
"target_amount": "50000.00",
"progress_after_contribution": "66.00",
"deadline": "2026-04-15T00:00:00Z"
},
"expires_at": "2026-03-10T12:10:00Z"
}
}

Validation errors:

ScenarioError CodeMessage
Pool is not a crowdfunding poolVALIDATION_ERRORPool is not a crowdfunding campaign
Campaign has endedVALIDATION_ERRORCrowdfunding campaign deadline has passed
Amount is zero or negativeVALIDATION_ERRORContribution amount must be greater than zero
Amount exceeds remaining targetVALIDATION_ERRORAmount exceeds remaining target (max: 17500.00)
Insufficient token balanceVALIDATION_ERRORInsufficient USDC balance

Submit Contribution

Submit a signed XDR transaction to finalize the contribution.

POST /api/agent/crowdfunding/submit-contribute

Request Body:

FieldTypeRequiredDescription
signed_xdrstringYesThe signed XDR transaction envelope
network_idintegerYesNetwork ID

curl:

curl -X POST https://home.dobprotocol.com/api/agent/crowdfunding/submit-contribute \
-H "X-API-Key: dob_ak_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"signed_xdr": "AAAAAgAAAABhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0...",
"network_id": 10
}'

Response (200 OK):

{
"success": true,
"data": {
"transaction_hash": "f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7",
"pool_address": "CA7QYNF7SOVZ4V4LXQHXWJQVGU3ZGR4A5OHCOQZSC7M2XZFKK67TYXZ",
"amount_contributed": "500.00",
"payment_token": "USDC",
"shares_allocated": 625,
"new_total_raised": "33000.00",
"progress_percent": 66.0,
"stellar_explorer_url": "https://stellar.expert/explorer/public/tx/f6a7b8c9..."
}
}

Complete Contribution Flow

import requests
from stellar_sdk import Keypair, TransactionBuilder, Network

API_KEY = "dob_ak_your_key_here"
SECRET_KEY = "SCZANGBA5YHTNYVVV3C7CAZMCLXPILHSE5BXBSOLRRUQSXKFHM7RI5OB"
BASE = "https://home.dobprotocol.com/api/agent"

headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
pool_address = "CA7QYNF7SOVZ4V4LXQHXWJQVGU3ZGR4A5OHCOQZSC7M2XZFKK67TYXZ"

# Step 1: Check the pool status
pool_resp = requests.get(
f"{BASE}/pools/{pool_address}",
headers={"X-API-Key": API_KEY},
params={"network_id": 10}
).json()

pool = pool_resp["data"]
print(f"Pool: {pool['name']}")
print(f"Target: {pool.get('target_amount', 'N/A')}")
print(f"Deadline: {pool.get('deadline', 'N/A')}")

# Step 2: Prepare contribution
prepare_resp = requests.post(f"{BASE}/crowdfunding/prepare-contribute",
headers=headers,
json={
"pool_address": pool_address,
"amount": "500.00",
"network_id": 10
}
).json()

if not prepare_resp["success"]:
print(f"Error: {prepare_resp['error']['message']}")
exit(1)

details = prepare_resp["data"]["transaction_details"]
print(f"Contributing {details['amount']} {details['payment_token']}")
print(f"Estimated shares: {details['estimated_shares']}")
print(f"Progress after: {details['progress_after_contribution']}%")

unsigned_xdr = prepare_resp["data"]["xdr"]

# Step 3: Sign locally
keypair = Keypair.from_secret(SECRET_KEY)
tx = TransactionBuilder.from_xdr(unsigned_xdr,
network_passphrase=Network.PUBLIC_NETWORK_PASSPHRASE)
tx.sign(keypair)
signed_xdr = tx.to_xdr()

# Step 4: Submit
submit_resp = requests.post(f"{BASE}/crowdfunding/submit-contribute",
headers=headers,
json={"signed_xdr": signed_xdr, "network_id": 10}
).json()

if submit_resp["success"]:
result = submit_resp["data"]
print(f"Contribution successful!")
print(f"TX: {result['transaction_hash']}")
print(f"Shares allocated: {result['shares_allocated']}")
print(f"Total raised: {result['new_total_raised']} ({result['progress_percent']}%)")
else:
print(f"Failed: {submit_resp['error']['message']}")

Monitoring Crowdfunding Progress

Use webhooks to get notified about crowdfunding events:

curl -X POST https://home.dobprotocol.com/api/agent/webhooks \
-H "X-API-Key: dob_ak_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/dob-events",
"events": ["crowdfunding_finalized", "crowdfunding_failed"],
"secret": "your_webhook_secret"
}'

See Webhooks for more details on event types and delivery.

Crowdfunding Event Payloads

When a crowdfunding campaign resolves, the webhook payload includes:

crowdfunding_finalized (target reached):

{
"event": "crowdfunding_finalized",
"timestamp": "2026-04-10T00:00:00Z",
"data": {
"pool_address": "CA7QYNF7SOVZ4V4LXQHXWJQVGU3ZGR4A5OHCOQZSC7M2XZFKK67TYXZ",
"pool_name": "Wind Turbine Collective",
"total_raised": "50000.00",
"contributor_count": 35,
"payment_token": "USDC"
}
}

crowdfunding_failed (target not reached):

{
"event": "crowdfunding_failed",
"timestamp": "2026-04-15T00:00:01Z",
"data": {
"pool_address": "CA7QYNF7SOVZ4V4LXQHXWJQVGU3ZGR4A5OHCOQZSC7M2XZFKK67TYXZ",
"pool_name": "Wind Turbine Collective",
"total_raised": "32500.00",
"target_amount": "50000.00",
"contributor_count": 18,
"refund_status": "processing"
}
}