Skip to main content

codespar_pay

Outbound spend. Money leaves the wallet or account your agent governs, under a signed mandate. Pix, card, boleto settlement, TED and wire, plus the reads around them (status, boleto quote, DDA, DICT keys and claims, Pix devolution).

13 min read
View MarkdownEdit on GitHub
Buy-sideYour agent is the spender: money leaves the wallet it governs, under a signed mandate.

Outbound spend — money leaves the wallet the agent governs.

tool codespar_pay18 actions2 move moneyalways required action

Collecting FROM a buyer instead? That is codespar_charge (sell-side). Settling in USDC or any on-chain asset? That is codespar_crypto_pay.

Actions

actionWhat it doesMoneyNeeds
pay
example below
Execute a payment or transfer under policy, mandate and routing: Pix, card, boleto settlement, TED or wiremoves moneyamountcurrencydescriptionrecipientorcopia_e_colaorcheckout_session_id
statusRead an existing payment, charge or boleto by id; the provider's status comes back verbatimnopayment_id
boleto_quoteRead a boleto's true current amount (interest and discount applied) without paying itnolinha_digitavel
dda_subscribeRegister the consumer's own CPF/CNPJ in the national DDA register so their boletos are mirrored herenodocumentidempotency_key
dda_statusRead a DDA registration (pending until the provider confirms, then active); local read onlynodocument
dda_list_dueList the mirrored boletos due between from_date and to_date; local read, own organization onlynofrom_dateto_date
dda_unsubscribeEnd a DDA registration the organization holds; needs no mandate so it stays possible after consent is revokednodocument
dict_claim_openOpen an OWNERSHIP or PORTABILITY claim on a Pix key for the consumer's own accountnokeyclaim_type
dict_claim_confirmConfirm a claim this consumer openednoclaim_id
dict_claim_cancelCancel a claim this consumer openednoclaim_id
dict_claim_statusRead one claim by idnoclaim_id
dict_claim_listList the consumer's claims on either side, with optional status and date filtersno
dict_claim_respondDonor side: CONFIRM (release the contested key) or REJECT (keep it)noclaim_idresponse
dict_key_registerRegister a Pix key on the consumer's own account: EMAIL, PHONE, CPF, CNPJ with a value, or EVP with nonenokey_type
dict_key_listList the Pix keys registered on the consumer's own accountno
dict_key_deleteRemove a Pix key from the consumer's own accountnokey
pix_devolutionReturn a received Pix to its original payer, or (payment_direction outbound) ask the rail to devolve a Pix the consumer sentmoves moneyend_to_end_ididempotency_key
pix_devolution_statusRead a devolution by devolution_id; poll this until settled, because settlement truth comes from the statementnodevolution_id

Unknown action: refused; nothing is dispatched. Measured 2026-09-09.

Names come from the published tool document (/v1/meta-tools.json, the same list the MCP server answers to tools/list); the one-line summaries and the money class are kept in the docs repository and checked against it on every build.

Example

action: "pay" over Pix, to a Pix key, from the consumer's governed wallet. Amounts are in minor units (centavos).

Call · tools/call
arguments
{
  "name": "codespar_pay",
  "arguments": {
    "action": "pay",
    "amount": 2500,
    "currency": "BRL",
    "method": "pix",
    "recipient": "payee@example.com",
    "description": "Example payout",
    "consumer_id": "consumer_0000",
    "idempotency_key": "pay_0000"
  }
}
Result · fields the tool document names
result
{
  "status": "PROCESSING",
  "settled": false,
  "status_message": "Accepted by the rail and settling; the wallet is already debited.",
  "initiation_type": "DICT",
  "charge_correlation": "none",
  "end_to_end_id": "e2e_0000"
}

A Pix cash-out is asynchronous: PROCESSING means accepted and settling within seconds, with the wallet already debited. Relay status_message to the user; do not surface a bare PROCESSING and do not treat it as a failure. A static QR (the code taped to a small merchant's wall) carries no charge identifier, so its result says charge_correlation: "none": settled means the rail moved the money, not that the merchant marked an order paid. Pass the end_to_end_id to the payee if they need to reconcile.

When to use

  • Paying a store order from codespar_shop. Pass the checkout_session_id with the same consumer_id used in the checkout; the backend resolves the exact Pix copia-e-cola server-side. Never re-type the long Pix code yourself (re-typing corrupts the CRC). If you already hold a copia-e-cola, pass it as copia_e_cola, never as recipient.
  • Paying a Pix key. recipient is the key (email, phone, CPF/CNPJ, EVP). For a destination with no key, recipient is a bank-account object; pass it literally, not JSON-stringified, because the argument's runtime type is what selects the path.
  • Settling an existing boleto. method: "boleto" with linha_digitavel. Quote first with action: "boleto_quote", then settle passing expected_amount_minor, so a stale quote fails cleanly instead of paying a different amount. This settles an existing boleto; it does not issue one (that is codespar_charge).
  • A bank wire. method: "ted" sends a real outbound TED to a bank account with no Pix key. It executes only under a consumer mandate whose signed withdrawal_allowlist names the destination; see Money and mandate.
  • Reading state. action: "status" reads a payment, charge or boleto by the id a previous codespar_pay or codespar_charge result returned, and answers with that provider's status verbatim (for example OVERDUE for an unpaid boleto). Pin provider when you already know which rail holds it.
  • The consumer's own Pix account. The dda_* actions register the consumer's document for national boleto visibility and list what they owe; the dict_key_* and dict_claim_* actions manage the keys on their account and the claim lifecycle. None of these moves money; the account is always resolved server-side from consumer_id.
  • Refunding a Pix. action: "pix_devolution" returns a received Pix to its original payer; with payment_direction: "outbound" it asks the rail to devolve a Pix the consumer sent. Poll pix_devolution_status, not status, until settled.

Arguments

The table mirrors the published schema for codespar_pay. action is required on every call.

Common

FieldTypeRequiredDescription
actionstringYesOne of pay, status, boleto_quote, dda_subscribe, dda_status, dda_list_due, dda_unsubscribe, dict_claim_open, dict_claim_confirm, dict_claim_cancel, dict_claim_status, dict_claim_list, dict_claim_respond, dict_key_register, dict_key_list, dict_key_delete, pix_devolution, pix_devolution_status. See the Actions table.
consumer_idstringNoWhose governed wallet pays, and whose account every DDA and DICT action targets. Defaults to the session user; for a checkout-originated Pix you must pass the consumer used in the checkout.
mandateIdstringNoPre-authorized mandate id
idempotency_keystringFor ted, pix_devolution, dda_subscribeStable per-operation key, reused verbatim on every retry of the same operation so a retry never dispatches a second payment. Strongly recommended for method: "boleto" (ent#783: without it every retry mints a fresh key and the provider cannot dedupe). On pix_devolution a new key for the same payment opens a new devolution of the remainder.

action: "pay"

FieldTypeRequiredDescription
amountnumberFor payMinor units (centavos for BRL). Must match the copia-e-cola's amount when paying a QR. On pix_devolution it is the partial amount to return (optional inbound, required outbound).
currencystringFor payBRL, USD, EUR
descriptionstringFor payPayment description
methodstringNopix, card, boleto, ted, wire. The schema declares a free-form string with no enum, so an unroutable value passes validation and dies at routing with no_eligible_providers. With action: "status", method (pix, ted, boleto) narrows which rail the status is read from.
countrystringNoISO 3166-1 alpha-2 for the eligibility rail (BR, US, MX, AR, CL, CO, INTL). Defaults to BR. US for cross-border USD card via Stripe ACP, INTL for hosted-checkout flows.
recipientstring | objectOne ofA Pix key, or an object { bank (ISPB), account, branch, tax_id, name, account_type? } for a destination with no key (a manual Pix cash-out, or the destination of method: "ted"). Pass the object literally. Do not put a copia-e-cola here.
copia_e_colastringOne ofA Pix copia-e-cola / BR Code to pay. The rail decodes it (static or dynamic) and debits the governed wallet.
checkout_session_idstringOne ofA codespar_shop checkout to settle. Preferred over copia_e_cola for a store order. Pass with consumer_id.
linha_digitavelstringWith boletoThe 47/48-digit linha digitável (or barcode) of an existing boleto to pay, or to quote with boleto_quote.
expected_amount_minornumberNomethod: "boleto" only: the exact amount a prior boleto_quote returned as true_amount. The settle re-consults the boleto and refuses with amount_mismatch when the fresh amount differs; no money moves on a stale quote.
client_finalitystringNomethod: "ted" only: the BaaS partner's finality code (1 | 3 | 4 | 5 | 7 | 9 | 10 | 100 | 110 | 99999; defaults to 1, a generic transfer). 99999 requires a description.

action: "status"

FieldTypeRequiredDescription
payment_idstringFor statusThe id a previous codespar_pay or codespar_charge result returned: an Asaas pay_* id, a BaaS transaction id, or a Pix endToEndId.
providerstringNoPin which provider holds the transaction, asaas | celcoin. Any other value is refused, not defaulted. Omit it and the read probes the rails that can answer, in order.

DDA (dda_*)

FieldTypeRequiredDescription
documentstringFor dda_subscribe, dda_status, dda_unsubscribeThe consumer's own CPF or CNPJ (punctuation optional). For dda_subscribe it is registered in the national DDA register, so it must be the document verified for that consumer's account at onboarding AND be named in the signed dda_allowlist of an active mandate of that consumer.
client_namestringNodda_subscribe only: the document holder's name as it should reach the provider. Defaults to consumer_id.
from_datestringFor dda_list_dueYYYY-MM-DD; list boletos due on or after this date.
to_datestringFor dda_list_dueYYYY-MM-DD; list boletos due on or before this date.

DICT keys and claims (dict_*)

FieldTypeRequiredDescription
keystringPer actionThe key being claimed (dict_claim_open), the key value to register (dict_key_register, omit for EVP), or the key to remove (dict_key_delete).
key_typestringFor dict_key_registerEMAIL | PHONE (E.164) | CPF | CNPJ (the account holder's own document; the alphanumeric CNPJ is accepted) | EVP (the provider mints a random key; pass no key). Optional hint on dict_claim_open.
claim_typestringFor dict_claim_openOWNERSHIP (contest a key resolving to another account) or PORTABILITY (re-point a key the consumer owns at another institution). Optional filter on dict_claim_list.
claim_idstringFor confirm, cancel, status, respondMust be a claim this consumer opened (confirm, cancel, status) or is the donor of (respond); any other id is refused.
responsestringFor dict_claim_respondCONFIRM (the donor releases the key) or REJECT (the donor keeps it).
reasonstringNoFor confirm, cancel, respond: USER_REQUESTED (default on cancel and reject) | ACCOUNT_CLOSURE | FRAUD | DEFAULT_OPERATION. For pix_devolution: the Pix return code, default MD06.
statusstringNodict_claim_list only: OPEN | WAITING_RESOLUTION | CONFIRMED | CANCELLED | COMPLETED.
date_fromstringNodict_claim_list only: from this date (YYYY-MM-DD).
date_tostringNodict_claim_list only: up to this date (YYYY-MM-DD).
limit_per_pagenumberNodict_claim_list only: page size.
pagenumberNodict_claim_list only: page number.

Pix devolution (pix_devolution*)

FieldTypeRequiredDescription
end_to_end_idstringFor pix_devolutionThe original payment's endToEndId, the only reference the rail accepts. Only a payment on the consumer's own account statement (last 7 days) can be devolved.
payment_directionstringNoinbound (default) devolves a payment the consumer received, sending the money back to its payer; outbound devolves a payment the consumer sent, returning it to the consumer's account (amount then required, one devolution per sent payment).
devolution_idstringFor pix_devolution_statusThe devolution to read, as returned by pix_devolution.

Errors and what to do

ErrorCauseWhat to do
invalid_argsA required argument for the action is missing, recipient and copia_e_cola are both absent on pay, or an unknown action. Nothing is dispatched.Fix the call against the Arguments table.
no_eligible_providersThe method × currency × country intent has no catalog line, or none of its providers is connected on this project. Nothing is dispatched.Check the rail in Notes, or connect the provider via codespar_manage_connections.
amount_mismatchmethod: "boleto" with expected_amount_minor, and the boleto's fresh true amount differs from the quote. No money moved.Re-quote with boleto_quote and show the new amount before settling.
dda_document_not_owneddda_subscribe for a document that is not the one verified for this consumer's account (including an account with no verified document). Nothing sent; the refusal never says which document was expected.Onboard the consumer whose document it is (codespar_kyc onboarding). Fixing the mandate does not clear this.
dda_document_unauthorizedThe document is not named in the signed dda_allowlist of an active mandate of this consumer. Nothing sent.The consumer names it at POST /v1/consents/init, field intent.dda_allowlist; there is no wildcard.
Refused TED with a consent next-stepmethod: "ted" to a destination the mandate's signed withdrawal_allowlist does not name. Nothing sent; the result reports dispatch: "unsent".Have the consumer sign a mandate naming ted:<ispb>:<branch>:<account>. A merchant "*" wildcard never authorizes it.
PROCESSING on a Pix cash-outNot an error: accepted and settling in seconds, wallet already debited.Relay status_message; poll action: "status" if you need the terminal state.
A devolution refused by the rail (outbound)The receiver is out of the rail's reach.It comes back as-is and is not a retry case.

Money and mandate

action: "pay" and action: "pix_devolution" move real money. Every spend leaves the consumer's governed wallet under a signed mandate: per-currency caps, per-transaction caps, allowlists and expiry are checked server-side before dispatch. Two destinations are pinned by the mandate text itself:

  • TED executes only when the mandate's signed withdrawal_allowlist names ted:<ispb>:<branch>:<account> (digits only). idempotency_key is required and checked before any money step, because the default correlation would make a second TED silently attach to the first. Every gate here is pre-dispatch and reports dispatch: "unsent"; an ambiguous provider outcome is never reported as unsent.
  • DDA registration exposes the titular's boletos, so it needs the document both verified at onboarding and named in the mandate's signed dda_allowlist. Neither condition substitutes for the other. dda_unsubscribe needs no mandate, so withdrawing a document from a national register stays possible after the consumer revokes consent.

Every other action (status, boleto_quote, dda_status, dda_list_due, all dict_*, pix_devolution_status) is a read or an account-management call: no money moves. A devolution always goes back to the original payer (inbound) or to the consumer's own account (outbound); it cannot be redirected.

Notes

Rails and providers

RailCurrencyCountryProviders
PixBRLBROutbound: Asaas (default) and a licensed Brazilian BaaS provider. Mercado Pago and 9 banks direct via mTLS (Banco do Brasil, Itaú, Bradesco, Santander, Caixa, Sicoob, Sicredi, C6, Original) sit on this surface as inbound charge lines and are refused for codespar_pay
CardBRLBRCielo (+ 3DS), Pagar.me
Boleto (settle an existing boleto)BRLBRLicensed Brazilian BaaS partner. Not a catalog line: this action bypasses the router and settles directly on the BaaS rail
TEDBRLBRLicensed Brazilian BaaS partner. Not a catalog line either: it bypasses the router and runs through the governed mandate lifecycle
CardMXNMXConekta
CardPENPECulqi
CardCLPCLTransbank
CardCOPCOWompi
Bank transferCOPCOCobre
WireCLPCLKhipu
WireUSDINTLAirwallex
CardUSDUSStripe ACP
Card · hosted checkoutUSD / EURINTLStripe ACP, Adyen, Airwallex, dLocal, Rapyd

The catalog carries 29 codespar_pay lines over 25 providers, but 10 of them (Mercado Pago and the nine bank /cob lines) are inbound charge lines the router refuses for a payout: 15 providers actually route outbound, across six countries (BR, MX, PE, CL, CO, US) plus the international corridors. The router fails over within a rail when the primary provider degrades (Pix BRL walks Asaas → the BaaS provider) and drops every line whose catalog entry declares money_in before scoring, so inbound lines are never picked and never reached by failover. Lines that declare no direction still pass; only Pix × BRL × BR has been adjudicated so far. See /dashboard/router for live failover telemetry, and cert auth for the banks' mTLS.

Operator setup. Each rail needs operator-stamped credentials in /dashboard/auth-configs: Asaas (API key; sandbox key for test, production key for live), Mercado Pago (access token, tied to a single seller account), Wompi / Conekta / Khipu / Transbank (per-provider API key and sandbox toggle). The dashboard wizard renders the right inputs from each server's auth_type in the catalog.

Async settlement. After codespar_pay returns, settlement happens via the provider webhook: the provider settles (seconds for Pix, hours-to-days for SPEI or wallet rails), POSTs a webhook, the backend correlates external_reference with idempotency_key, and session.paymentStatus(tool_call_id) reports succeeded with final_amount_minor and settled_at. See async settlement for per-provider idempotency-key shapes and SSE streaming for the streaming variant.

From the SDK. There is no typed wrapper for codespar_pay; call session.execute() with the same arguments as the MCP call. The executor output lives under data.

const result = await session.execute("codespar_pay", {
  action: "pay",
  amount: 2500,
  currency: "BRL",
  method: "pix",
  recipient: "payee@example.com",
  description: "Example payout",
  consumer_id: "consumer_0000",
  idempotency_key: "pay_0000",
});
console.log(result.tool_call_id, result.data);
result = session.execute("codespar_pay", {
    "action": "pay",
    "amount": 2500,
    "currency": "BRL",
    "method": "pix",
    "recipient": "payee@example.com",
    "description": "Example payout",
    "consumer_id": "consumer_0000",
    "idempotency_key": "pay_0000",
})
print(result["tool_call_id"], result["data"])

Result envelope (SDK), as previously documented. session.execute returns { success, data, error, tool_call_id, server }; for action: "pay" the page used to document data as { id, status, settled?, status_message?, amount?, currency?, method? } plus rail-specific extras (end_to_end_id on Pix; linha_digitavel, beneficiary, due_date on boleto), and action: "status" as { id, status, billing_type, value, due_date }. This revision did not re-verify those field lists against the runtime; the fields the tool document itself names are the ones in the Example above.

@codespar/types drifts. The package's copy of this schema (SHARED_META_TOOL_DEFINITIONS.codespar_pay) lags the API in both directions (ent#933): it still names usdc and sepa as methods, neither of which routes, and it lacks fields the API publishes. This page follows the API, which is what decides.

codespar_pay | CodeSpar