Selling online in Brazil means touching six different systems for every single order. Payment gateway, tax authority, shipping carrier, messaging platform, ERP, and banking reconciliation. Miss one and you are either breaking the law, losing packages, or burning cash on manual reconciliation.
This is not a convenience problem. NF-e issuance is a legal requirement. SEFAZ authorization must happen before the product ships. Pix confirmations expire. Shipping labels need to be generated before carrier pickup windows close. These are not nice-to-haves you can defer to v2.
The Complete Loop is CodeSpar's orchestration primitive that runs all six steps in sequence, with retry logic, error handling, and rollback built in. This tutorial shows you how to use it.
Before CodeSpar: 6 manual steps, 45 minutes, 3 people. After: 1 agent call, 12 seconds, zero humans.
What the Complete Loop actually does
Every e-commerce order in Brazil requires this exact sequence. Not approximately this sequence. This exact sequence, in this order, with each step depending on the output of the previous one:
- Charge via Pix. Generate a Pix QR code, wait for payment confirmation from the PSP. The Pix expires in 30 minutes by default. If the customer does not pay, the entire loop aborts. You cannot issue an invoice for an unpaid order.
- Issue NF-e. Submit the Nota Fiscal Eletronica to SEFAZ (the state tax authority). SEFAZ validates the tax calculation, product codes (NCM), and business registration (CNPJ). Authorization can take 1-15 seconds. Without an authorized NF-e, shipping the product is a federal crime under Brazilian tax law.
- Generate shipping label. Request a label from the carrier (Correios, Jadlog, or others via Melhor Envio). The label contains the tracking code, delivery estimate, and the NF-e DANFE number. Carriers will not accept packages without a valid NF-e reference.
- Notify the customer. Send the order confirmation, tracking code, and NF-e PDF via WhatsApp (or SMS/email as fallback). Brazil has 99% WhatsApp penetration. Customers expect real-time updates.
- Register in ERP. Create the sales order in the ERP (Omie, Bling, Tiny) with the payment reference, NF-e number, and shipping tracking. The ERP is the system of record for accounting, tax reporting, and inventory management.
- Reconcile in banking. Match the Pix credit in the bank account (via Stark Bank or similar) against the order. This closes the financial loop and ensures no revenue leaks between the PSP settlement and the bank balance.
Skip step 2 and you are evading taxes. Skip step 3 and the carrier rejects the package. Skip step 5 and your accountant cannot close the month. Skip step 6 and you will never know if R$50,000 in Pix payments actually settled in your bank account.
NF-e issuance is mandatory for all commercial transactions in Brazil (Lei 8.846/94, updated by Ajuste SINIEF 07/05). Operating without NF-e carries fines of 1% of transaction value per day, plus potential criminal liability. The Complete Loop ensures compliance by making NF-e issuance a non-optional step in the orchestration.
Install the SDK
The SDK is distributed as five npm packages. For this tutorial, you need the core SDK and the Vercel AI SDK adapter:
The packages and their roles:
@codespar/sdk-- Core: sessions, tools, execute, loop, managed auth, billing hooks@codespar/vercel-- Vercel AI SDK adapter with execute() functions@codespar/claude-- Claude API adapter (if using Anthropic SDK directly)@codespar/openai-- OpenAI adapter (function calling format)@codespar/mcp-- MCP config generator for IDE integration (Claude Desktop, Cursor)
Configure environment variables
CodeSpar API keys are scoped to an organization. Each key starts with csk_live_ (production) or csk_test_ (sandbox). Test keys hit mock servers that return realistic data without touching real payment gateways or SEFAZ. Always use test keys during development.
Create a session
A session is a scoped execution context. It bundles together a user, a set of MCP servers (determined by the preset), auth credentials, and policy rules. Sessions are the billing unit.
The brazilian preset connects to six MCP servers: Zoop (payments), Nuvem Fiscal (NF-e), Melhor Envio (shipping), Z-API (WhatsApp), Omie (ERP), and Stark Bank (banking). Each server exposes 10-20 tools. The SDK collapses all of them into 6 meta tools so the LLM sees a clean, unambiguous tool surface.
Run the Complete Loop with generateText
The simplest way to run the Complete Loop is to let the LLM orchestrate it. You describe the order in natural language and the model calls the right tools in the right sequence:
The LLM reads the prompt, identifies the six steps, and calls the meta tools in order. Each meta tool routes to the correct MCP server, executes the real API call, and returns the result. The events fire as each step completes.
Run the Complete Loop with session.loop()
For production workloads, you want deterministic orchestration rather than relying on the LLM to figure out the sequence. The session.loop() API gives you explicit control over each step, with built-in retry logic and error handling:
Error handling: what actually goes wrong
In production, every step can fail. Here is what goes wrong at each stage and how to handle it.
Pix payment timeout
Pix QR codes expire. The default expiration is 30 minutes, but some PSPs allow as little as 5 minutes. If the customer does not scan and confirm within the window, the payment times out.
Always set Pix expiration to at least 30 minutes for desktop users. Mobile users who are already in their banking app can pay in seconds, but desktop users need to switch devices. Monitor your timeout rate: anything above 15% means your expiration window is too short.
NF-e SEFAZ rejection
SEFAZ can reject an NF-e for dozens of reasons: invalid NCM code, incorrect ICMS calculation, expired digital certificate, server timeout, or the state's SEFAZ being offline entirely. Each scenario requires different handling.
Never auto-retry a SEFAZ rejection. Rejections mean the data is wrong (bad NCM, invalid CFOP, tax math error). Retrying the same payload will produce the same rejection. SEFAZ timeouts are different and can be retried safely. Always distinguish between rejection (data error) and timeout (infrastructure error).
Shipping label generation failure
Melhor Envio aggregates multiple carriers. If the primary carrier (Correios PAC) is unavailable, you can fall back to alternatives:
WhatsApp delivery failure
WhatsApp delivery can fail if the number is not registered, the Z-API session has expired, or Meta's infrastructure is having issues. Always have a fallback channel:
ERP sync failure
ERP systems go down. Omie has maintenance windows. Bling rate-limits aggressively. The correct pattern is to queue and retry, not to block the order:
Steps 1-3 (payment, NF-e, shipping) are blocking. If they fail, the order cannot proceed. Steps 4-6 (notification, ERP, reconciliation) are non-blocking. They should be queued and retried asynchronously. Never let an ERP timeout prevent a customer from receiving their order confirmation.
Real-time streaming with session.sendStream()
For user-facing applications where you need to show progress as the loop executes, use session.sendStream() instead of generateText. This returns a Server-Sent Events stream that emits events as each tool call starts and completes:
What happened under the hood
When you call generateText or session.loop() with the CodeSpar tools, here is what the SDK does at each layer:
- Policy check. The PolicyBridge verifies the R$1,249 charge is within the session's budget limit. If the charge would exceed the budget, a typed
BudgetExceededErroris thrown before any API call is made. Rate limits and time-window policies are also checked. - Meta tool routing. The MetaToolExecutor receives
codespar_payand resolves it to the Zoop MCP server. It scores all tools on that server using keyword matching against the input parameters and selectsZOOP_CREATE_CHARGEas the best match. - Auth injection. The AuthManager retrieves stored OAuth2 tokens for Zoop, checks expiration, refreshes if needed, and injects the bearer token into the MCP request headers. Your code never touches a raw token.
- MCP execution. The tool call is sent to the Zoop MCP server via Streamable HTTP transport. The server validates the request, calls the Zoop REST API, and returns the result.
- Event detection. The EventDetector analyzes the tool call name and response payload to fire typed commerce events (
payment.completed,nfe.issued). Detection works with both English and Portuguese response text. - Billing. Every tool call is logged to the
session_tool_callstable with input/output payloads, duration, and status. These records drive metered billing via Stripe. One tool call equals one billing unit. - Budget tracking. The PolicyBridge records the R$1,249 charge against the session budget. Remaining budget is available via
session.budget().
Latency breakdown: where does the time go?
A Complete Loop takes 8-15 seconds end-to-end in production, depending on carrier response times and SEFAZ load. Here is the typical latency breakdown for each step:
| Step | API | P50 | P99 |
|---|---|---|---|
| Pix charge | Zoop | 1.2s | 3.5s |
| NF-e issuance | SEFAZ | 2.1s | 8.0s |
| Shipping label | Melhor Envio | 1.8s | 4.2s |
| WhatsApp msg | Z-API | 0.8s | 2.0s |
| ERP registration | Omie | 1.5s | 3.8s |
| Bank reconciliation | Stark Bank | 0.6s | 1.5s |
| Total (sequential) | 8.0s | 23.0s | |
SEFAZ is the bottleneck. NF-e authorization involves cryptographic signature verification and cross-state validation, which is why P99 can spike to 8 seconds. During SEFAZ maintenance windows (typically Sunday nights), the contingencia path adds 200-500ms of overhead but avoids the outage entirely.
Steps 4-6 (notify, ERP, reconcile) can optionally run in parallel since they do not depend on each other's output. Running them concurrently cuts 2-4 seconds from the total:
Billing: what a Complete Loop costs
Every tool call in a Complete Loop is a billing unit. A standard 6-step loop consumes 6 tool calls. With the LLM-orchestrated approach (generateText), the model may make additional discovery calls, so expect 8-10 tool calls per loop.
| Plan | Tool calls/mo | Loops/mo | Price |
|---|---|---|---|
| Hobby | 20K | ~2,500 | $0 |
| Starter | 200K | ~25,000 | $29 |
| Growth | 2M | ~250,000 | $229 |
| Enterprise | Custom | Custom | Custom |
The Hobby tier gives you 20,000 tool calls per month for free. That is roughly 2,500 Complete Loops, enough for most small businesses processing a few dozen orders per day.
Production deployment checklist
Before you deploy the Complete Loop to production, make sure you have:
- Production API keys. Switch from
csk_test_tocsk_live_. Test keys hit sandbox MCP servers. Live keys hit real APIs. Do not discover this in production. - Provider credentials. Authorize each MCP server via
session.authorize()with production OAuth tokens or API keys from Zoop, Nuvem Fiscal, Melhor Envio, Z-API, Omie, and Stark Bank. - Digital certificate. NF-e requires an A1 digital certificate (PFX file) issued by a Brazilian certificate authority. Upload it via the dashboard or pass it in the session config. Certificates expire annually.
- Webhook endpoints. Set up
codespar.handleWebhook()to receive async events from providers (Pix confirmation, shipping status updates, SEFAZ retransmission results). - Budget limits. Set realistic budget limits per session. A single order for R$50,000 will blow through a R$1,000 budget limit and throw
BudgetExceededErrorbefore the Pix charge is created. - Monitoring. Track loop completion rate, step-level latency, and failure reasons. The SDK emits structured logs that work with any observability stack (Datadog, Grafana, CloudWatch).
- Dead letter queue. Set up a queue for failed non-blocking steps (notification, ERP, reconciliation) so they can be retried without losing the order.
- Idempotency. Always pass an order ID or idempotency key in your tool calls. If a loop is retried after a partial failure, idempotent calls ensure you do not double-charge the customer or issue duplicate NF-e.
The business case
We built the Complete Loop because we watched e-commerce operations teams in Brazil do the same six steps manually for every order, every day.
| Manual | CodeSpar | |
|---|---|---|
| Steps | 6 (across 6 different UIs) | 1 (single SDK call) |
| Time per order | 35-45 minutes | 8-15 seconds |
| People involved | 2-3 (ops, finance, shipping) | 0 (fully automated) |
| Error rate | 5-8% (data entry errors) | <0.1% (validated inputs) |
| NF-e compliance | Manual, often delayed | Immediate, with contingencia |
| Reconciliation | End of month, manual | Real-time, per-transaction |
| Cost at 100 orders/day | ~R$15K/mo (labor) | ~$29/mo (Starter plan) |
The math is simple. A mid-size e-commerce operation processing 100 orders per day spends R$15,000/month on operations staff to do these six steps manually. The Complete Loop replaces that with a $29/month Starter plan and 12 seconds of compute time per order.
That is not a 10% improvement. That is a 500x cost reduction with better accuracy, faster fulfillment, and real-time compliance.
Check the results
Next steps
Now that you have the Complete Loop running:
- Add real provider credentials via
session.authorize() - Create mandates for recurring payments with
session.createMandate() - Set up webhook handling with
codespar.handleWebhook()for async provider events - Use
session.sendStream()for real-time UI updates in customer-facing apps - Monitor loop performance in the dashboard (completion rate, latency, failure reasons)
- Explore the full server catalog across 4 countries (Brazil, Mexico, Colombia, Argentina)
- Read the SDK design post for architecture details on sessions, meta tools, and managed auth
All MCP servers are MIT licensed and available on npm. The SDK is at @codespar/sdk@0.2.0. The source is at github.com/codespar/codespar-core.
Full source code for this tutorial is available on GitHub. Questions? Open an issue or reach us at team@codespar.dev.