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
- Pool creator sets up a crowdfunding pool with a target amount, deadline, and payment token.
- Contributors send payment tokens to the pool during the campaign.
- If target is reached before the deadline, the pool finalizes: shares are allocated proportionally, and the pool becomes active for distributions.
- 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:
| Field | Type | Required | Description |
|---|---|---|---|
pool_address | string | Yes | Crowdfunding pool contract address |
amount | string | Yes | Contribution amount (decimal string, in payment token units) |
network_id | integer | Yes | Network 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:
| Scenario | Error Code | Message |
|---|---|---|
| Pool is not a crowdfunding pool | VALIDATION_ERROR | Pool is not a crowdfunding campaign |
| Campaign has ended | VALIDATION_ERROR | Crowdfunding campaign deadline has passed |
| Amount is zero or negative | VALIDATION_ERROR | Contribution amount must be greater than zero |
| Amount exceeds remaining target | VALIDATION_ERROR | Amount exceeds remaining target (max: 17500.00) |
| Insufficient token balance | VALIDATION_ERROR | Insufficient USDC balance |
Submit Contribution
Submit a signed XDR transaction to finalize the contribution.
POST /api/agent/crowdfunding/submit-contribute
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
signed_xdr | string | Yes | The signed XDR transaction envelope |
network_id | integer | Yes | Network 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"
}
}