---
title: Pix Payment Agent
description: The simplest agent you can build with CodeSpar. Create a Pix charge, generate a QR code, and send it to the customer via WhatsApp — in ~50 lines of code.
---

<ActionBar githubPath="content/docs/cookbooks/pix-payment-agent.mdx" markdownPath="/api/docs-md/cookbooks/pix-payment-agent" />

<MetaStrip items={[
  { label: "TIME", value: "~10 min" },
  { label: "PROVIDER", value: (<><ServerChip name="OpenAI" accent /><span style={{ color: "var(--color-fd-muted-foreground)", fontSize: 12 }}>gpt-4o</span></>) },
  { label: "SERVERS", value: (<><ServerChip name="asaas" /><ServerChip name="z-api" /></>) },
]} />

Create a Pix charge, generate the QR code, and send it to the customer via WhatsApp. The simplest agent you can build with CodeSpar — two steps, one conversation.

<PixFlow
  steps={[
    { label: "Create Pix charge", tool: "codespar_charge", description: "Routed to Asaas — QR code + copy-paste key", iconKey: "qr" },
    { label: "Send via WhatsApp", tool: "codespar_notify", description: "Routed to Z-API — entrega instantânea no WhatsApp brasileiro", iconKey: "send" },
  ]}
  qr={{ amount: "150,00", description: "Pro Plan" }}
/>

<Callout>
**`codespar_charge` vs `codespar_pay`** — `charge` is *inbound* (buyer pays merchant: Pix QR / boleto / card). `pay` is *outbound* (merchant pays out: payouts, refunds, supplier transfers). This cookbook is the inbound flavor. After the buyer settles, correlate via [`session.paymentStatus(toolCallId)`](/docs/concepts/async-settlement) (poll) or `session.paymentStatusStream` (SSE — see [/docs/concepts/sse-streaming](/docs/concepts/sse-streaming)).
</Callout>

## Conversation preview

What the agent does when you call `pixAgent("+5511...", 15000, "Pro Plan")`.

<ChatPreview
  agentName="payment assistant"
  sessionId="sb_pix_a3"
  messages={[
    { role: "user", content: "Create a Pix payment of R$150 for `Pro Plan - Monthly` and send to `+5511999887766`." },
    { role: "agent", content: "Vou gerar o Pix de R$ 150,00 e enviar o QR code no WhatsApp." },
    { role: "agent", content: "Pronto. Pix criado (`pay_abc123`) e QR code enviado para o WhatsApp do cliente. Pagamento aguardando." },
  ]}
  toolCalls={[
    { name: "codespar_charge", server: "asaas", status: "done", duration: "620ms" },
    { name: "codespar_notify", server: "z-api", status: "done", duration: "340ms" },
  ]}
  footer="2 tool calls · 960ms total · 2 LLM iterations"
  sandboxLink="/dashboard/sandbox"
/>

## Prerequisites

Install the SDK and the OpenAI provider adapter:

```bash
npm install @codespar/sdk @codespar/openai openai
```

Set your environment variables:

```bash title=".env"
CODESPAR_API_KEY=csk_live_...
OPENAI_API_KEY=sk-...
```

<Callout>
You'll need active accounts on **Asaas** and **Z-API**. CodeSpar will prompt you to authenticate both on first run.
</Callout>

## Full agent code

```typescript title="pix-agent.ts"
import OpenAI from "openai";
import { CodeSpar } from "@codespar/sdk";
import { getTools, handleToolCall } from "@codespar/openai";

const openai = new OpenAI();
const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });

async function pixAgent(phone: string, amount: number, description: string) {
  const session = await codespar.create("user_123", {
    servers: ["asaas", "z-api"],
  });

  try {
    const tools = await getTools(session);

    const messages = [
      { role: "system", content: "You are a Brazilian payment assistant..." },
      {
        role: "user",
        content: `Create Pix of R$${amount / 100} for "${description}", send to ${phone}`,
      },
    ];

    let response = await openai.chat.completions.create({ model: "gpt-4o", tools, messages });
    while (response.choices[0].message.tool_calls?.length) {
      // ... handle tool calls, feed results back, call LLM again
    }

    return response.choices[0].message.content;
  } finally {
    await session.close();
  }
}
```

## Variations

### Add boleto fallback
Pass `payment_methods: ["pix", "boleto"]` to `codespar_charge` and let the customer pick at checkout.

### Chain an invoice
After payment confirmation, chain `codespar_invoice` to issue an NF-e automatically.

### Swap to Claude
Replace `@codespar/openai` with `@codespar/claude`. The agent logic is identical.

### Python version
For FastAPI services or async jobs, the same flow in Python — no framework-adapter needed, `session.send()` runs the agent loop on the backend:

```python title="pix_agent.py"
from codespar import CodeSpar

cs = CodeSpar()  # reads CODESPAR_API_KEY

def pix_agent(phone: str, amount: int, description: str) -> str:
    with cs.create("user_123", servers=["asaas", "z-api"]) as session:
        result = session.send(
            f'Create a Pix of R${amount / 100:.2f} for "{description}", '
            f"send the QR code to {phone} via WhatsApp."
        )
    return result.message
```

Swap `CodeSpar` for `AsyncCodeSpar` and `with` for `async with` to run inside FastAPI. See [Quickstart (Python)](/docs/quickstart-python).

## Next steps

<NextStepsGrid items={[
  { label: "COOKBOOK", title: "E-Commerce Checkout", description: "Full checkout flow with invoicing and shipping — the Pix agent's big sibling.", href: "/docs/cookbooks/ecommerce-checkout" },
  { label: "COOKBOOK", title: "Multi-Provider Agent", description: "Route payments across Stripe, Asaas, and Mercado Pago automatically.", href: "/docs/cookbooks/multi-provider" },
  { label: "CONCEPT", title: "Sessions", description: "Session lifecycle, scoping, and when to close vs reuse.", href: "/docs/concepts/sessions" },
  { label: "REFERENCE", title: "OpenAI Adapter", description: "Full API reference for @codespar/openai.", href: "/docs/providers/openai" },
]} />
