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/crypto-addresses` for the address 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-webhook-signature`, HMAC-SHA256)
2. Check idempotency (`x-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/crypto-addresses`
*(Call `get_endpoint` with method `post`, path `/api/v1/crypto-addresses` in the CoinCircuit MCP for the full request/response schema.)*
```json
{
"chain": "tron",
"address": "TF6yMCJqFcT6wFFutxVmRocKgJFD5imKUT",
"label": "Vendor Alice - Tron wallet",
"isDefault": true
}
```
Supported chains: `"bitcoin"`, `"ethereum"`, `"solana"`, `"bsc"`, `"tron"`, `"base"`, `"arbitrum"`.
The response `data.id` is the UUID you use as `recipientId` in payouts.
### 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.