WhatsApp agent with Pix payments
Collect Pix with a Tyxter payment request through Abacate Pay — the recommended merchant payment path — or send Meta's native Pix message from an eligible Brazil WABA.
payment.paid event confirms settlement. A native WhatsApp Pix message does not create a Tyxter payment request or reconcile payment state.Recommended: transparent Abacate Pix
This is the recommended merchant Pix path. It works for every WhatsApp Business Account — no Meta payments onboarding is involved — and settlement is confirmed by the Tyxter payment request's own payment.paid event. POST /v1/payments with provider_options.abacate_pay.charge_type = "pix". Creation is asynchronous, so poll GET /v1/payments/{payment_id} until pix_copy_paste is non-null, then send it as a normal WhatsApp text message. First read GET /v1/provider-connections/status: Abacate Pay must be connected and selected as the environment default, and the returned channels.payments.active_mode must equal abacate_pay before you send provider_options.abacate_pay. An unresolved provider selection fails with payment_provider_selection_required; options that do not match the active provider fail with payment_provider_options_unsupported. Reading provider status requires the API key scope provider_connections:read; without it, the call fails with 403 insufficient_scope. The connectionless sandbox default does not emulate transparent Pix.
const providerStatus = await tyxter.providerConnections.status();
if (providerStatus.channels.payments.active_mode !== "abacate_pay") {
throw new Error("Connect and select Abacate Pay before requesting transparent Pix");
}
const created = await tyxter.payments.create(
{
amount_brl_centavos: 12900,
description: "Order #123",
external_reference: "ord_123",
provider_options: { abacate_pay: { charge_type: "pix" } },
},
{ idempotencyKey: crypto.randomUUID() },
);
let payment = created;
for (let attempt = 0; attempt < 30 && !payment.pix_copy_paste; attempt += 1) {
if (
payment.status === "failed" ||
payment.status === "expired" ||
payment.status === "cancelled"
) {
throw new Error("Pix creation ended with " + payment.status);
}
await new Promise((resolve) => setTimeout(resolve, 1_000));
payment = await tyxter.payments.retrieve(created.id);
}
if (!payment.pix_copy_paste) throw new Error("Pix code is still pending");
// This is a free-form WhatsApp text send and requires an open 24-hour
// customer-service window; otherwise POST /v1/messages returns service_window_required.
await tyxter.whatsapp.sendText({
from: "phone_number_id",
to: "+5511999999999",
body: "Pay with Pix (copy and paste):\n" + payment.pix_copy_paste,
});The final text send is free-form WhatsApp messaging, so it requires an open 24-hour customer-service window. Without one, Tyxter rejects POST /v1/messages synchronously with service_window_required; use an approved template outside the window. Subscribe to payment.paid for this Tyxter payment request. That event records merchant PSP settlement reported by Abacate Pay; it is not a Meta order-status signal.
Alternative: native WhatsApp Pix
The native interactive.order_details message is an optional in-chat checkout upgrade, not the primary Tyxter payment path. Use it only when Meta Payments API in Brazil is enabled for the sending WhatsApp Business Account; most integrations should use the Abacate path above. This is a free-form interactive message, so the conversation must have an open 24-hour customer-service window. Without one, Tyxter rejects synchronously with service_window_required. Tyxter returns 202 Accepted only after contract, authentication, feature, and service-window prevalidation; Meta then evaluates WABA and message eligibility at provider-send time. The acceptance response does not promise Meta delivery, so inspect normal message status and webhooks.
{
"channel": "whatsapp",
"sender": { "type": "whatsapp_phone_number", "id": "phone_number_id" },
"recipient": { "type": "phone_e164", "id": "+5511999999999" },
"message": {
"type": "interactive",
"interactive": {
"type": "order_details",
"body": { "text": "Review and pay your order." },
"action": {
"name": "review_and_pay",
"parameters": {
"reference_id": "ord_123-20260807",
"type": "digital-goods",
"payment_type": "br",
"payment_settings": [{
"type": "pix_dynamic_code",
"pix_dynamic_code": {
"code": "00020101021226700014br.gov.bcb.pix...",
"merchant_name": "Example Store",
"key": "39580525000189",
"key_type": "CNPJ"
}
}],
"currency": "BRL",
"total_amount": { "value": 12900, "offset": 100 }
}
}
}
}
}The caller supplies reference_id, the dynamic Pix code, merchant_name, key, and key_type. There is no payment_id lookup or order_status update in this message contract. Meta transports the payment details but does not reconcile merchant settlement; confirm payment with your merchant or PSP.
Tyxter endpoints
LLM routing
Tyxter LLM routing is available for BYOK inbound automation, but it is optional for this architecture. Prefer app-owned LLM orchestration when the agent must call tools Tyxter does not own.