Marketplace
The marketplace enables secondary trading of pool shares. Shareholders can list their shares for sale at a specified price, and buyers can purchase available listings.
Read endpoints require the read scope. Trade endpoints require the trade scope.
Authentication: X-API-Key header
How Trading Works: Prepare / Submit
All trade operations follow a prepare/submit pattern to keep private keys secure:
- Prepare -- Your agent sends the trade parameters. The API returns an unsigned Stellar XDR transaction envelope.
- Sign locally -- Your agent signs the XDR with the wallet's secret key. The private key never leaves your infrastructure.
- Submit -- Your agent sends the signed XDR back. The API submits it to the Stellar network and returns the result.
Agent API Stellar Network
| | |
|-- POST /prepare-buy ------->| |
|<-- unsigned XDR ------------| |
| | |
| (sign XDR locally) | |
| | |
|-- POST /submit-buy -------->| |
| |-- submit transaction ------->|
| |<-- confirmation -------------|
|<-- result ------------------| |
Signing XDR in Python
from stellar_sdk import Keypair, TransactionBuilder, Network
def sign_xdr(unsigned_xdr: str, secret_key: str, network: str = "PUBLIC") -> str:
"""Sign an unsigned Stellar XDR transaction envelope."""
keypair = Keypair.from_secret(secret_key)
if network == "PUBLIC":
passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
else:
passphrase = Network.TESTNET_NETWORK_PASSPHRASE
tx = TransactionBuilder.from_xdr(unsigned_xdr, network_passphrase=passphrase)
tx.sign(keypair)
return tx.to_xdr()
Read Endpoints (read scope)
List All Active Listings
Retrieve all active share listings across all pools.
GET /api/agent/marketplace/listings
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
network_id | integer | -- | Filter by network |
payment_token | string | -- | Filter by payment token (e.g., USDC) |
sort | string | created_desc | Sort: created_desc, created_asc, price_asc, price_desc |
page | integer | 1 | Page number |
limit | integer | 20 | Results per page (max 100) |
curl:
curl "https://home.dobprotocol.com/api/agent/marketplace/listings?network_id=10&sort=price_asc&limit=10" \
-H "X-API-Key: dob_ak_your_key_here"
Python:
import requests
resp = requests.get(
"https://home.dobprotocol.com/api/agent/marketplace/listings",
headers={"X-API-Key": API_KEY},
params={"network_id": 10, "sort": "price_asc", "limit": 10}
)
listings = resp.json()["data"]
for listing in listings:
print(f"{listing['pool_name']}: {listing['shares_amount']} shares "
f"@ {listing['price_per_share']} {listing['payment_token']}")
Response (200 OK):
{
"success": true,
"data": [
{
"sale_address": "SALE_7f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c",
"pool_address": "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC",
"pool_name": "Solar Farm Alpha",
"pool_ticker": "SFA",
"network_id": 10,
"seller_address": "GDJTUK3ER3M7LFHHWQMFANJA3SEC7QP3LNU3NKGFBLWF4QMFR5HR7I4T",
"shares_amount": 200,
"price_per_share": "1.50",
"total_price": "300.00",
"payment_token": "USDC",
"payment_token_address": "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75",
"is_active": true,
"created_at": "2026-03-05T10:00:00Z"
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 34
}
}
Pool Listings
Retrieve all active listings for a specific pool.
GET /api/agent/marketplace/listings/:poolAddress
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
poolAddress | string | Pool contract address |
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
network_id | integer | -- | Network ID |
sort | string | price_asc | Sort: price_asc, price_desc, created_desc |
curl:
curl "https://home.dobprotocol.com/api/agent/marketplace/listings/CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC?network_id=10&sort=price_asc" \
-H "X-API-Key: dob_ak_your_key_here"
Response (200 OK):
{
"success": true,
"data": [
{
"sale_address": "SALE_7f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c",
"seller_address": "GDJTUK3ER3M7LFHHWQMFANJA3SEC7QP3LNU3NKGFBLWF4QMFR5HR7I4T",
"shares_amount": 200,
"price_per_share": "1.50",
"total_price": "300.00",
"payment_token": "USDC",
"is_active": true,
"created_at": "2026-03-05T10:00:00Z"
},
{
"sale_address": "SALE_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"seller_address": "GDU3QXHDURHXNKFI4H5QC7JTQOCGS63C25FVTTBGROQOLKV7Q2BAWGYP",
"shares_amount": 100,
"price_per_share": "1.75",
"total_price": "175.00",
"payment_token": "USDC",
"is_active": true,
"created_at": "2026-03-06T14:00:00Z"
}
]
}
Pool Marketplace Stats
Retrieve marketplace statistics for a pool, including floor price, volume, and listing count.
GET /api/agent/marketplace/stats/:poolAddress
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
poolAddress | string | Pool contract address |
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
network_id | integer | -- | Network ID |
curl:
curl "https://home.dobprotocol.com/api/agent/marketplace/stats/CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC?network_id=10" \
-H "X-API-Key: dob_ak_your_key_here"
Response (200 OK):
{
"success": true,
"data": {
"pool_address": "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC",
"pool_name": "Solar Farm Alpha",
"network_id": 10,
"floor_price": "1.50",
"highest_price": "2.10",
"payment_token": "USDC",
"active_listings": 5,
"total_shares_listed": 850,
"volume_24h": "450.00",
"volume_7d": "2100.00",
"volume_30d": "8500.00",
"total_volume": "15200.00",
"total_sales": 42
}
}
Trade Endpoints (trade scope)
Prepare Buy
Prepare an unsigned XDR transaction to buy shares from a marketplace listing.
POST /api/agent/marketplace/prepare-buy
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
listing_id | string | Yes | The sale_address of the listing to buy |
amount | integer | No | Number of shares to buy (defaults to all available) |
network_id | integer | Yes | Network ID |
curl:
curl -X POST https://home.dobprotocol.com/api/agent/marketplace/prepare-buy \
-H "X-API-Key: dob_ak_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"listing_id": "SALE_7f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c",
"amount": 100,
"network_id": 10
}'
Python:
# Step 1: Prepare
resp = requests.post(
"https://home.dobprotocol.com/api/agent/marketplace/prepare-buy",
headers={"X-API-Key": API_KEY},
json={
"listing_id": "SALE_7f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c",
"amount": 100,
"network_id": 10
}
)
unsigned_xdr = resp.json()["data"]["xdr"]
Response (200 OK):
{
"success": true,
"data": {
"xdr": "AAAAAgAAAABhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0...",
"transaction_details": {
"listing_id": "SALE_7f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c",
"shares": 100,
"price_per_share": "1.50",
"total_cost": "150.00",
"payment_token": "USDC",
"seller_address": "GDJTUK3ER3M7LFHHWQMFANJA3SEC7QP3LNU3NKGFBLWF4QMFR5HR7I4T"
},
"expires_at": "2026-03-10T12:10:00Z"
}
}
The unsigned XDR expires after 10 minutes. Sign and submit before it expires.
Submit Buy
Submit a signed XDR transaction to complete a share purchase.
POST /api/agent/marketplace/submit-buy
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/marketplace/submit-buy \
-H "X-API-Key: dob_ak_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"signed_xdr": "AAAAAgAAAABhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0...",
"network_id": 10
}'
Python (complete buy flow):
from stellar_sdk import Keypair, TransactionBuilder, Network
API_KEY = "dob_ak_your_key_here"
SECRET_KEY = "SCZANGBA5YHTNYVVV3C7CAZMCLXPILHSE5BXBSOLRRUQSXKFHM7RI5OB"
BASE = "https://home.dobprotocol.com/api/agent"
# Step 1: Prepare
prepare_resp = requests.post(f"{BASE}/marketplace/prepare-buy",
headers={"X-API-Key": API_KEY},
json={
"listing_id": "SALE_7f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c",
"amount": 100,
"network_id": 10
}
).json()
unsigned_xdr = prepare_resp["data"]["xdr"]
# Step 2: 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 3: Submit
submit_resp = requests.post(f"{BASE}/marketplace/submit-buy",
headers={"X-API-Key": API_KEY},
json={"signed_xdr": signed_xdr, "network_id": 10}
).json()
if submit_resp["success"]:
print(f"Purchase complete! TX: {submit_resp['data']['transaction_hash']}")
else:
print(f"Failed: {submit_resp['error']['message']}")
Response (200 OK):
{
"success": true,
"data": {
"transaction_hash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"listing_id": "SALE_7f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c",
"shares_bought": 100,
"total_cost": "150.00",
"payment_token": "USDC",
"stellar_explorer_url": "https://stellar.expert/explorer/public/tx/a1b2c3d4..."
}
}
Prepare List Shares
Prepare an unsigned XDR transaction to list shares for sale on the marketplace.
POST /api/agent/marketplace/prepare-list
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
pool_address | string | Yes | Pool contract address |
shares_amount | integer | Yes | Number of shares to list |
price_per_share | string | Yes | Price per share (decimal string) |
payment_token | string | Yes | Payment token symbol (e.g., "USDC") |
network_id | integer | Yes | Network ID |
curl:
curl -X POST https://home.dobprotocol.com/api/agent/marketplace/prepare-list \
-H "X-API-Key: dob_ak_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"pool_address": "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC",
"shares_amount": 200,
"price_per_share": "1.50",
"payment_token": "USDC",
"network_id": 10
}'
Response (200 OK):
{
"success": true,
"data": {
"xdr": "AAAAAgAAAABhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0...",
"transaction_details": {
"pool_address": "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC",
"shares_amount": 200,
"price_per_share": "1.50",
"total_listing_value": "300.00",
"payment_token": "USDC"
},
"expires_at": "2026-03-10T12:10:00Z"
}
}
Submit List
Submit a signed XDR transaction to finalize a share listing.
POST /api/agent/marketplace/submit-list
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/marketplace/submit-list \
-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": "d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5",
"sale_address": "SALE_c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8",
"pool_address": "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC",
"shares_listed": 200,
"price_per_share": "1.50",
"payment_token": "USDC",
"stellar_explorer_url": "https://stellar.expert/explorer/public/tx/d4e5f6a7..."
}
}
Prepare Cancel
Prepare an unsigned XDR transaction to cancel an active listing.
POST /api/agent/marketplace/prepare-cancel
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
listing_id | string | Yes | The sale_address of the listing to cancel |
network_id | integer | Yes | Network ID |
curl:
curl -X POST https://home.dobprotocol.com/api/agent/marketplace/prepare-cancel \
-H "X-API-Key: dob_ak_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"listing_id": "SALE_c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8",
"network_id": 10
}'
Response (200 OK):
{
"success": true,
"data": {
"xdr": "AAAAAgAAAABhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0...",
"transaction_details": {
"listing_id": "SALE_c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8",
"shares_returned": 200
},
"expires_at": "2026-03-10T12:10:00Z"
}
}
Submit Cancel
Submit a signed XDR transaction to finalize listing cancellation.
POST /api/agent/marketplace/submit-cancel
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/marketplace/submit-cancel \
-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": "e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6",
"listing_id": "SALE_c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8",
"shares_returned": 200,
"stellar_explorer_url": "https://stellar.expert/explorer/public/tx/e5f6a7b8..."
}
}
Complete Trading Bot Example
import requests
from stellar_sdk import Keypair, TransactionBuilder, Network
class DobMarketplaceBot:
BASE = "https://home.dobprotocol.com/api/agent"
def __init__(self, api_key: str, secret_key: str, network_id: int = 10):
self.api_key = api_key
self.keypair = Keypair.from_secret(secret_key)
self.network_id = network_id
self.headers = {"X-API-Key": api_key, "Content-Type": "application/json"}
self.passphrase = (Network.PUBLIC_NETWORK_PASSPHRASE
if network_id == 10
else Network.TESTNET_NETWORK_PASSPHRASE)
def _sign(self, unsigned_xdr: str) -> str:
tx = TransactionBuilder.from_xdr(unsigned_xdr,
network_passphrase=self.passphrase)
tx.sign(self.keypair)
return tx.to_xdr()
def get_listings(self, pool_address: str) -> list:
resp = requests.get(
f"{self.BASE}/marketplace/listings/{pool_address}",
headers=self.headers,
params={"network_id": self.network_id, "sort": "price_asc"}
)
return resp.json()["data"]
def buy_cheapest(self, pool_address: str, max_price: str, shares: int):
"""Buy shares from the cheapest listing if below max price."""
listings = self.get_listings(pool_address)
if not listings:
print("No active listings found.")
return None
cheapest = listings[0]
if float(cheapest["price_per_share"]) > float(max_price):
print(f"Floor price {cheapest['price_per_share']} exceeds max {max_price}")
return None
# Prepare
prepare = requests.post(f"{self.BASE}/marketplace/prepare-buy",
headers=self.headers,
json={
"listing_id": cheapest["sale_address"],
"amount": min(shares, cheapest["shares_amount"]),
"network_id": self.network_id
}
).json()
if not prepare["success"]:
print(f"Prepare failed: {prepare['error']['message']}")
return None
# Sign and submit
signed = self._sign(prepare["data"]["xdr"])
result = requests.post(f"{self.BASE}/marketplace/submit-buy",
headers=self.headers,
json={"signed_xdr": signed, "network_id": self.network_id}
).json()
return result
# Usage
bot = DobMarketplaceBot(
api_key="dob_ak_your_key_here",
secret_key="SCZANGBA5YHTNYVVV3C7CAZMCLXPILHSE5BXBSOLRRUQSXKFHM7RI5OB"
)
result = bot.buy_cheapest(
pool_address="CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC",
max_price="2.00",
shares=100
)