# Marketplace Vendor Payouts

> Collect crypto from buyers and pay vendors out in crypto.

Section: Build with AI
Source: https://coincircuit.io/docs/guides/marketplace-settlement/
Interactive version: https://coincircuit.io/api-reference?tab=guides&guide=marketplace-settlement

Tags: Payments, Payouts, Balance

Paste this prompt into Claude, ChatGPT, or any AI tool. It works best with the CoinCircuit MCP server connected: https://mcp.coincircuit.io

---

You are helping me integrate CoinCircuit into my existing marketplace for buyer payments and vendor payouts. I have the CoinCircuit MCP server connected.

**If you have access to the CoinCircuit MCP server, call these tools for the most accurate and detailed schema outputs:**
- Call `get_endpoint` with method `post` and path `/api/v1/payments` in the CoinCircuit MCP for the checkout session creation schema.
- Call `get_endpoint` with method `get` and path `/api/v1/balance` for the balance response schema.
- Call `get_endpoint` with method `post` and path `/api/v1/payouts` for the payout creation schema.
- Call `get_endpoint` with method `post` and path `/api/v1/recipients` for the recipient creation schema.
- Call `get_endpoint` with method `get` and path `/api/v1/rates/convert` for the exchange rate schema.
- Call `get_schema` with name `PaymentCompletedWebhookDto` for the payment.completed webhook payload.
- Call `get_schema` with name `PayoutSuccessWebhookDto` for the payout.success webhook payload.
- Call `get_schema` with name `PayoutFailedWebhookDto` for the payout.failed webhook payload.

Use the live MCP data as your source of truth. The details below are a guide, but if the MCP returns something different, trust the MCP.

## API Basics

- **Base URL:** `https://api.coincircuit.io`
- **Auth:** `x-api-key` header on every request.

## Project Context

I have a marketplace that collects payment from buyers, takes a platform fee, and distributes the rest to vendors. I'm integrating CoinCircuit for crypto payments. CoinCircuit does not natively split payments, so the architecture is:

```
Buyer pays crypto -> CoinCircuit collects -> Merchant balance grows -> I pay out to vendors
```

**Important:** Vendor distribution uses crypto payouts (USDT to wallet addresses). Fiat payouts go only to the merchant's own bank account, not to third-party vendors.

## What I Need You to Implement

### 1. Collect payment from buyer

**Endpoint:** `POST /api/v1/payments`
*(Call `get_endpoint` with method `post`, path `/api/v1/payments`, section `example` in the CoinCircuit MCP for a ready-to-use sample request.)*

Create a checkout session for the full order amount. Store the vendor split in `metadata`:

```json
{
  "title": "Order #ORD-123",
  "description": "Marketplace order with 2 vendors",
  "amount": "150.00",
  "currency": "USD",
  "customer": { "email": "buyer@example.com" },
  "metadata": {
    "orderId": "ORD-123",
    "platformFee": "15.00",
    "vendors": [
      { "vendorId": "v1", "amount": "90.00", "cryptoAddressId": "addr_v1_uuid" },
      { "vendorId": "v2", "amount": "45.00", "cryptoAddressId": "addr_v2_uuid" }
    ]
  },
  "successUrl": "https://marketplace.com/order/ORD-123/success",
  "cancelUrl": "https://marketplace.com/cart"
}
```

Response gives you `data.reference` for the checkout SDK and `data.url` for the hosted page.

### 2. On payment.completed, queue vendor payouts

When the `payment.completed` webhook fires:

*(Call `get_schema` with name `PaymentCompletedWebhookDto` in the CoinCircuit MCP to see every field in the webhook payload, including settlements and transaction details.)*

1. Verify the signature (`x-coincircuit-signature`, HMAC-SHA256)
2. Check idempotency (`x-coincircuit-delivery-id`)
3. Parse vendor split from `data.session.metadata.vendors`
4. Lock the conversion rate from `data.session.payment.conversionRate` and `data.session.settlements`
5. Deduct your platform fee
6. Queue crypto payouts for each vendor

### 3. Check balance before paying vendors

**Endpoint:** `GET /api/v1/balance?currency=USDT`
*(Call `get_endpoint` with method `get`, path `/api/v1/balance` in the CoinCircuit MCP for the full response schema.)*

Verify `availableBalance` covers all vendor payouts plus fees. The response includes `totalBalance`, `availableBalance`, and `pendingBalance`.

### 4. Pay vendors via crypto payouts

**Endpoint:** `POST /api/v1/payouts`
*(Call `get_endpoint` with method `post`, path `/api/v1/payouts`, section `request` in the CoinCircuit MCP for the exact request body with all field validations.)*

For each vendor:
```json
{
  "method": "crypto",
  "currency": "USDT",
  "amount": "90.00",
  "recipientId": "addr_v1_uuid",
  "narration": "Vendor payout - Order ORD-123",
  "reference": "PAYOUT-ORD123-V1"
}
```

Each payout returns with `status: "pending"`. The response includes `fee`, `total` (amount + fee), and `conversion` details if cross-currency.

### 5. Track vendor payout status

*(Call `get_schema` with name `PayoutSuccessWebhookDto` and `PayoutFailedWebhookDto` in the CoinCircuit MCP for the full webhook payloads.)*

**Webhook events:**
- `payout.success` - funds delivered. `data.payout.txHash` and `data.payout.completedAt` confirm delivery.
- `payout.failed` - payout failed. `data.payout.failureReason` explains why. Funds return to your balance. Retry or escalate.

### 6. Vendor onboarding

Each vendor saves their crypto wallet address:

**Endpoint:** `POST /api/v1/recipients`
*(Call `get_endpoint` with method `post`, path `/api/v1/recipients` in the CoinCircuit MCP for the full request/response schema.)*

```json
{
  "type": "crypto_address",
  "label": "Vendor Alice - Tron wallet",
  "isDefault": true,
  "details": {
    "chain": "tron",
    "address": "TF6yMCJqFcT6wFFutxVmRocKgJFD5imKUT"
  }
}
```

Supported chains: `"bsc"`, `"tron"`, `"solana"`, `"base"`, `"ethereum"`.

The response `data.id` is the UUID you use as `recipientId` in payouts. If a matching recipient already exists, the existing one is returned instead of a duplicate.

### 7. Exchange rates for display

**Endpoint:** `GET /api/v1/rates/convert?from=USDT&to=NGN`
*(Call `get_endpoint` with method `get`, path `/api/v1/rates/convert` in the CoinCircuit MCP for the full response schema. You can also call `get_all_conversion_rates` in the CoinCircuit MCP to see all live rates.)*

Returns:
```json
{
  "success": true,
  "data": {
    "rate": 1462.1,
    "from": "USDT",
    "to": "NGN",
    "timestamp": "2025-01-15T10:30:00.000Z"
  }
}
```

Both `from` and `to` must be uppercase. Supports fiat (NGN, USD, EUR, GBP) and crypto (BTC, ETH, USDT, USDC, BNB, SOL, XRP).

Use this to show vendors their expected payout in local currency.

## Constraints

- Store vendor split data in payment `metadata` so your webhook handler can process it
- Check `availableBalance` before creating vendor payouts
- Use unique `reference` values per payout. Duplicates are rejected.
- Exchange rates fluctuate. Lock amounts at payment time using the session's conversion rate from `data.session.settlements.gross.conversionRate`.
- Fiat payouts go only to the merchant's own bank account. Use crypto payouts for vendor distribution.
- Payout `amount` is a string. Balance values are also strings.
