Marketplace Payout
Split a marketplace transaction into platform fee + seller payout. One agent, two settled transactions, full audit trail.
A marketplace collects a charge from the buyer, keeps its platform fee, and pays the seller the remainder. Two settled transactions, one on each lane of the rate card: the charge is money arriving (Get paid, 1%, cap R$2.00) and the payout is money leaving under mandate (Move, 10 bps, cap R$2.00). The agent handles the whole flow: capture, reconcile, payout, invoice.
The money flow
| Step | Meta-tool | Direction | Billed |
|---|---|---|---|
| 1. Charge buyer (R$1,000) | codespar_pay (card via Stripe) | Buyer → Platform | Get paid: 1% of R$1,000 hits the cap, R$2.00 |
| 2. Calculate split (platform fee 15%) | — | — | (logic, not billed) |
| 3. Payout seller (R$850 via Pix) | codespar_pay (payout via Stark Bank) | Platform → Seller | Move: 10 bps of R$850, R$0.85 |
| 4. Issue NF-e for platform fee (R$150) | codespar_invoice | — | Operate lane, included while in preview |
Total CodeSpar fee: R$2.85, regardless of how many providers the flow touches. Card and Pix rail fees pass through at the partner's price on their own line, and the first R$1,000 settled per month per lane is free.
Prerequisites
npm install @codespar/sdk @codespar/claude @anthropic-ai/sdkYou need the merchant's own Stripe account + a Stark Bank account with outbound Pix enabled. See Authentication > Connect Links for user-level OAuth.
Full agent code
import Anthropic from "@anthropic-ai/sdk";
import { CodeSpar } from "@codespar/sdk";
import { getTools, handleToolUse, toToolResultBlock } from "@codespar/claude";
const claude = new Anthropic();
const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
interface Order {
order_id: string;
buyer: { email: string; card_token: string };
seller: { id: string; bank_pix_key: string; cnpj: string };
gross_amount: number; // centavos, e.g. 100000 = R$1,000
platform_fee_bps: number; // basis points, e.g. 1500 = 15%
}
async function marketplacePayout(order: Order) {
const session = await codespar.create(order.seller.id, {
servers: ["stripe", "stark-bank", "nuvem-fiscal"],
metadata: {
order_id: order.order_id,
marketplace_flow: "payout_v1",
},
});
try {
const tools = await getTools(session);
const platformFee = Math.round(order.gross_amount * order.platform_fee_bps / 10000);
const payoutAmount = order.gross_amount - platformFee;
const messages: Anthropic.MessageParam[] = [
{
role: "user",
content: `
Execute a marketplace order settlement:
1. Charge R$${(order.gross_amount / 100).toFixed(2)} on the buyer card (token: ${order.buyer.card_token}) via Stripe.
2. Once the charge settles, pay out R$${(payoutAmount / 100).toFixed(2)} via Pix to the seller key ${order.seller.bank_pix_key} via Stark Bank.
3. Issue an NF-e for the platform fee R$${(platformFee / 100).toFixed(2)} to seller CNPJ ${order.seller.cnpj} via the fiscal provider.
4. Return the charge_id, payout_id, and nfe_access_key.
Stop immediately if the charge fails — do not attempt payout or invoice.
`,
},
];
let response = await claude.messages.create({
model: "claude-opus-4-6",
max_tokens: 4096,
tools,
messages,
});
let iterations = 0;
while (response.stop_reason === "tool_use" && iterations < 10) {
const blocks = response.content.filter(
(b): b is Anthropic.ToolUseBlock => b.type === "tool_use",
);
const results = await Promise.all(
blocks.map(async (block) => {
const out = await handleToolUse(session, block);
return toToolResultBlock(block.id, out);
}),
);
messages.push({ role: "assistant", content: response.content });
messages.push({ role: "user", content: results });
response = await claude.messages.create({
model: "claude-opus-4-6",
max_tokens: 4096,
tools,
messages,
});
iterations++;
}
const final = response.content.find(
(b): b is Anthropic.TextBlock => b.type === "text",
);
return final?.text ?? "";
} finally {
await session.close();
}
}Deterministic mode
If the flow never branches and you do not need LLM reasoning mid-run, swap the Claude loop for loop(session, config). Faster, cheaper, easier to debug:
import { CodeSpar } from "@codespar/sdk";
const cs = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
const session = await cs.create("user_123", { servers: ["asaas"] });
// ---cut---
declare const order: {
gross_amount: number;
buyer: { card_token: string };
seller: { bank_pix_key: string; cnpj: string };
};
declare const platformFee: number;
// ---cut---
import { loop } from "@codespar/sdk";
const result = await loop(session, {
steps: [
{
tool: "codespar_pay",
params: { method: "card", amount: order.gross_amount, card_token: order.buyer.card_token },
},
{
tool: "codespar_pay",
params: (prev) => ({
action: "payout",
method: "pix",
amount: order.gross_amount - platformFee,
pix_key: order.seller.bank_pix_key,
source_payment_id: (prev[0].data as { payment_id: string }).payment_id,
}),
},
{
tool: "codespar_invoice",
params: (prev) => ({
type: "nfe",
amount: platformFee,
customer: { cnpj: order.seller.cnpj },
reference: (prev[0].data as { payment_id: string }).payment_id,
}),
},
],
abortOnError: true, // stop if the charge fails
});Variations
Escrow / milestone release
Hold the charge in an escrow account until the seller fulfills the order. Pay out only after a shipping-confirmed event. Escrow is part of the managed runtime, not a separate price line: your agent calls a single codespar_pay with escrow: true and releases it with a follow-up call after the fulfillment webhook.
Split across multiple sellers
For a multi-vendor cart (N sellers per order), turn the payout step into a loop:
steps: [
{ tool: "codespar_pay", params: { method: "card", amount: order.gross } },
...order.sellers.map((seller) => ({
tool: "codespar_pay",
params: { action: "payout", method: "pix", amount: seller.share, pix_key: seller.pix },
})),
]Each payout is one settled transaction on the Move lane.
Next steps
E-Commerce Checkout
Brazilian e-commerce flow — buyer pays via Pix, NF-e gets issued, label generated, customer notified on WhatsApp. Same shape that ships in codespar-core/examples/brazilian-ecommerce.
Pay Documents and Batches
Turn boleto PDFs, Pix QR images, Pix keys and CSV or XLSX lists into one batch, review what the rail resolved, confirm the exact list and pay it, with a result per item. Same contract over the API, the TypeScript and Python SDKs, the CLI and the `@codespar/mcp` server.