Platform

Billing

Prepaid credits, BRL only, R$50 minimum. Tyxter charges one flat transport fee when Meta accepts an outbound WhatsApp message, discounted by your plan. Sandbox is free. Production API-key access is blocked at or below -R$5, except for supported recovery endpoints.

Meta bills your own payment method separately from Tyxter. Each business phone number gets 1,000 delivered service messages free from Meta every month; Meta charges from the 1,001st. Tyxter transport fees still apply. Read Meta pricing and free service messages for the allowance, message categories, and payment setup.

Recover from a credit block

A credit block engages at or below -R$5 and lifts as soon as the balance is above -R$5. The Billing page shows a persistent alert while the refreshed wallet reports production credit access blocked. An organization owner or admin can open the existing top-up flow from that alert; other members see recovery guidance. Add enough credit to make the balance positive. The alert clears when the refreshed production_blocked field is false. A balance above -R$5 but still below zero lifts the block without paying an unpaid phone rental month. A positive balance may still be too low to cover the next rental fee. Clearing this credit block does not clear other account limits. Sandbox remains unaffected by this credit block.

How it works

Top up

Top-ups are created from the dashboard, where the signed-in user can use Stripe Elements or PIX without exposing dashboard session endpoints as public integration APIs. The balance is credited atomically when Stripe's webhook marks the intent as succeeded.

Minimum top up is R$50 (5000 centavos). Lower amounts get a 400 validation_error.

Refunds

Unused prepaid credit can be refunded if you ask support within 7 days of the top-up or package purchase it came from, up to the unused balance on the day you ask. Promotional or bonus credit is never refunded, and after those 7 days unused credit is not refundable. Approved refunds are paid to the original payment method within 30 business days of the request, and the refunded amount is debited from the balance.

The monthly fee for a number Tyxter provisions is non-refundable, in full or in part, once it has been charged, including when you release or disconnect the number, delete the WABA, or Meta blocks sending; the first month is charged once the line is provisioned. A fee returns to the balance automatically only while it is still a reservation, which only the first month ever is: it returns when provisioning fails. Releasing a number stops future renewals.

Balance and ledger

GET/v1/billing/balance
GET/v1/billing/ledger

The ledger is a cursor-paginated stream of credits (top ups) and debits (usage records). Each entry carries the trace_id that produced it so you can reconcile a charge back to the exact message. A non-zero uncollected_brl on a debit entry is the part of a usage charge that could not be collected without crossing the -R$5 production credit floor; a rental line written before rental fees were debited in full can carry one too. Entries are listed newest first by date (recorded_at for a debit), and no rental reservation appears. How rental lines are dated, and why your balance can move without a new entry, is set out in How number rental is billed. A payment completion fee is the exception: its hold and its release are listed as hold and release entries (see Payment fees).

Phone rental renewal decisions (deprecated)

GET/v1/billing/phone-renewals

Deprecated: for each number's current month, read the renewal field of GET /v1/phone-numbers and GET /v1/phone-numbers/{id} (see the renewal policy). This route keeps answering with the renewal cycles recorded by the earlier prepaid renewal design; no new cycle is recorded. Under the current policy the month is charged on its 1st (see How number rental is billed), so a recorded cycle tracks no prepayment. Each cycle keeps its immutable period and amount, safe lifecycle timestamps, and whether it was funded, at risk, renewed, released, or cancelled. A cancelled cycle records an operational lifecycle closure, not a non-payment release; a month charged on its 1st may then show as cancelled. Status and recommended actions describe the stored cycle, not a fresh wallet assessment. The business number display is nullable after release, and no provider identifiers, reservation data, raw evidence, or notification-recipient data is returned. The next_renewal_at and release_cutoff_at dates are captured provider schedule and cutoff snapshots, separate from the UTC billing period. Later invalidation does not erase these historical dates. The renewal_warning_48h_at and renewal_warning_24h_at dates are always null: those warnings are retired. The grace_selected_at and grace_ends_at dates describe retained grace; an unknown end stays null. A renewed retained cycle records a wallet charge and can still have active grace or outstanding wallet debt.

Rate card

GET/v1/rate-cards/current

Rate cards are effective-dated. The active card is the one whose window covers now, and it is the authoritative source for the meter rates below — the transport fee, the payment fees and the Meta reference rates. Plan fees, multipliers, throughput, and phone allowances are not on the rate card; those live on the plan catalog further down. Each entry carries a kind so you can tell what Tyxter actually debits (billed) from what is reproduced for reference only (meta_reference).

What Tyxter charges

Tyxter bills one flat transport fee when Meta accepts an outbound WhatsApp message — msg.transport, R$0.05 per message — whatever the conversation category. A subscription plan discounts that fee by a multiplier. It is a discount on the per-message rate, not a bundled quota: you still pay for every message, just less per message.

msg.transport   R$0.05 / message      base rate
                x 1.00  = R$0.05      Free (no subscription)
                x 0.60  = R$0.03      Standard
                x 0.32  = R$0.016     Growth

The other meters Tyxter bills to your credit balance:

phone.number.month       R$50.00 / number / month (numbers Tyxter provisions for you)
phone.management.month   R$20.00 / number / month (numbers imported from your own Salvy account, once no Standard or Growth plan covers them)
msg.instagram.outbound   R$0.05 / message
tts.characters           R$0.0001 / character rendered
llm.tokens.used          R$0.015 / 1k tokens (input + output)
template.generation      R$0.05 / generation (production only)

These are list prices; the rate card in force is the source for each meter’s price: read it on GET /v1/rate-cards/current.

Production inbound-audio transcription uses stt.audio.second when Tyxter’s platform credential runs the provider and stt.audio.second.byok when your connected OpenAI STT credential does. Set up OpenAI STT BYOK in the media guide. The chosen source and meter stay fixed for that run, including automatic retries. A new manual retry may select the configuration available at that time. Disconnecting your OpenAI STT credential withdraws the override, so every transcription that was not already attributed to it — including one still queued — meters at stt.audio.second on Tyxter’s platform credential again. Starting 24 August 2026 at 00:01 America/Sao_Paulo (03:01 UTC), the platform rate is R$0.0043 per audio second and the BYOK rate is R$0.0005 per audio second. A 60-second successful transcript is R$0.2580 with Tyxter’s credential or R$0.0300 with BYOK. Pricing uses the rate card effective at the usage event, so earlier usage keeps its earlier price. Consult GET /v1/rate-cards/current for the currently effective card. If the selected meter has no active entry, Tyxter fails the transcript before reading audio or calling the provider and records transcription_billing_rate_unavailable. It does not silently switch to the platform credential or create zero-priced production usage.

The plan multiplier applies to msg.transport and msg.failed_processing. Every other meter above bills at its flat rate on every plan — an outbound Instagram message costs R$0.05 whether you are on Free or on Growth.

Payment fees

Accepting a payment is a service, so Tyxter charges two fees for every payment it accepts: a merchant payment request created with POST /v1/payments or from the dashboard, and an agentic payment created with POST /v1/agentic/payments. The fees apply whichever credential runs the payment, your own provider connection or the Tyxter platform Iniciador app.

payment.initiation   R$0.10 / payment              charged when the payment is accepted, kept whatever the outcome
payment.completion   R$0.0001 / principal centavo  1% of the amount, held when the payment is accepted

How number rental is billed

These rules cover the phone.number.month rental of a production number Tyxter provisions for you. Ordering a number in sandbox is free and reserves nothing. All times are UTC; 00:00 UTC on the 1st is 21:00 the day before in Brasília (UTC-3).

A number you bring yourself costs nothing to keep. phone.number.month is a rental pass-through for numbers Tyxter provisions on your behalf. A number you connect from your own Meta WhatsApp Business account is never metered — R$0 per month. A number imported from your own Salvy account is free while you have a Standard or Growth plan and through the end of the UTC month in which that plan ends; after that, keeping Tyxter’s management of it costs the monthly phone.management.month fee, charged on the 1st, described in Phone numbers. Either kind still counts toward your plan’s production phone-number allowance.

Read managed-number payment and service

GET /v1/billing/phone-management reads the API key's project and environment. Charged coverage.state: prepaid alone does not prove payment. current_month_payment_status is paid or unpaid for the current enrollment's funded UTC month, using durable unpaid-month evidence, and not_charged without a funded fee. service_state distinguishes serving, disabled_unpaid_month_end, funding_required and not_serving; provider eligibility, enrollment fences and structural suspension affect service separately from payment. This is not a general send-eligibility verdict.

disable_at is the free-plan month-end deadline for live, unfenced, unended charged coverage whose month stays unpaid; paid plans have no deadline. It remains visible during the release window and is null from the 18:00 UTC cutoff. Provider eligibility and structural suspension do not remove billing disable exposure. Sandbox funded zero fees read paid, otherwise not_charged, with no unpaid state, deadline or unpaid-disable service state. summary.next_charge_brl totals only fees at summary.next_charge_at, or null without a scheduled charge; monthly_total_brl remains the total across all scheduled instants. Older responses may omit these added nullable fields.

Example dates

Each example is a number ordered, approved, delivered and active on the same day.

Failed message processing

Eligible persisted WhatsApp failures before provider acceptance use msg.failed_processing, initially 10% of the transport rate. Permanent template, recipient and asset mistakes qualify. Internal or unknown faults, ambiguous network failures, temporary upstream errors, capacity deferrals and account restrictions are free, as is API validation that creates no message. After provider acceptance, the full transport fee remains due even if delivery fails; a message cannot receive both charges. Historical failures without an eligibility receipt are not backbilled.

At the repository fixture transport price R$0.0500, failure processing is R$0.0050 on Free, R$0.0030 on Standard and R$0.0016 on Growth. Consult the live rate card for current prices. The failure-time card and settlement-time plan are snapshotted in the existing usage record transport breakdown, with no Meta reference or conversation category. Failure processing never consumes package quota. Cash collection is limited by credit headroom; any uncollected remainder remains recorded. Sandbox models prices without cash or package debit.

Meta reference rates

Meta bills your outbound WhatsApp messages directly to your own Meta account, per delivered message, at a rate that depends on which of its categories the message falls into. Tyxter is not the billing party for them, never debits them from your credit balance, and never marks them up. They appear on the rate card as kind: "meta_reference".

Development rate cards may contain placeholder Meta references. Tyxter does not publish those as customer estimates. A usage response returns a non-null estimated_external_meta_cost only after an official BRL source and its effective date pass independent verification; until then the amount is null and missing quantity is reported explicitly.

When available, the estimate is calculated from the immutable rate selected at each usage event's timestamp. It stays separate from cost_brl, your credit balance, ledger, invoice, package quota, and the always-zero pre-BSP meta_pass_through_fee_brl. Meta's own account and invoice remain authoritative.

Sandbox usage reports the same estimate fields so you can model production Meta costs before going live. Sandbox messages are simulated inside Tyxter — Meta never delivers or bills them, so a sandbox estimate is a modeling aid, not an incoming charge.

Why Meta invoices you and not Tyxter — and who owns the WhatsApp Business Account that invoice belongs to — is set out on the Tyxter and Meta page.

Plans

GET/v1/billing/plans
GET/v1/billing/plan

A plan is a monthly subscription that lowers the per-message transport fee and raises your throughput and phone-number limits. Free is the absence of a subscription rather than something you buy — you get the base rate and the smallest limits, with no monthly fee.

Plans, like the credit balance, attach to the organization: one subscription covers every project and environment under it, and the discounted per-message rate applies to traffic from all of them. There is no per-project plan or wallet. Per-project attribution survives the shared wallet — invoices are generated per project and a monthly spend limit can be set per project in the dashboard. Integrations that run one project per end customer are covered on the Multi-tenant platforms page.

PlanMonthlyPer WhatsApp messageSustained throughputProduction numbers
Free—R$0.0530 msg/s1
StandardR$209.90R$0.0360 msg/s3
GrowthR$419.90R$0.016120 msg/sNo fixed limit

GET /v1/billing/plans is the live catalog and the source of truth for the money columns. Every offering carries monthly_fee_brl, annual_pix_fee_brl, platform_fee_multiplier, max_phones, and the already-multiplied net_transport_rate_brl — read that last field and you have the exact per-message rate the plan bills, with no arithmetic. It lists what you can buy, so Free is not in it. To read the plan your organization is on right now, Free included, call GET /v1/billing/plan, where status: "none" means Free. Paying a year up front by PIX is also offered, at each plan’s annual_pix_fee_brl.

The catalog also exposes salvy_byok_enabled as plan eligibility: an eligible plan can import numbers from your own Salvy account, with no management fee while it stays active and through the end of the UTC month in which it ends. Standard and Growth are eligible; Free, pending payment, and custom plans are false by default. A paid plan also keeps the numbers Tyxter rents for you from the month-end release for non-payment, and the numbers you imported from the month-end disable. Eligibility is separate from the rollout fence, so availability follows the deployment rollout. An already paid term keeps management free through the end of the UTC month in which its period ends, even if a later renewal payment fails.

Sustained throughput is the ceiling your plan sets on outbound sends, with a bucket of exactly twice that many messages available for a burst. It is a ceiling, not a guarantee: each number sends at whichever is lower, your plan’s rate or that number’s own Meta messaging limit — so a number Meta still rates at 30 msg/s sends at 30 msg/s on every plan. The dashboard shows the effective limit per number.

The phone-number allowance counts active production numbers of both kinds — provisioned by Tyxter and brought from your own Meta account — across every project in the organization, whichever WABA each number belongs to. Going past it returns 402 plan_phone_limit_reached on the next order, provision, connect or Salvy import (POST /v1/phone-numbers/import-salvy), and again when an owner or admin approves an order; numbers you already have are never removed when you move to a smaller plan.

Numbers Tyxter provisions for you have their own limit, separate from that allowance: 1 on Free, 3 on Standard and 10 on Growth by default. On Growth that reads as up to 10 Tyxter-provisioned numbers by default (R$50/number/month) — more on request · unlimited bring-your-own numbers, because Growth sets no plan allowance at all; on Free and Standard the allowance above still counts your own numbers too. The ceiling counts only active production numbers Tyxter provisioned: a number you brought from your own Meta account never counts toward it, and sandbox provisioning is never capped. An order or provision request past the ceiling, or an approval that would pass it, returns 409 phone_number_limit_reached — release a Tyxter-provisioned number to free its slot, or contact us and we will raise the limit for your organization. The plan allowance is evaluated first, so an organization already at its allowance sees 402 plan_phone_limit_reached and should upgrade rather than ask for a higher ceiling. The ceiling is not published on GET /v1/billing/plans; max_phones there is the plan allowance, which counts numbers of both kinds.

Subscribing, switching, and cancelling are documented on the Billing API reference.

Spend limit

Set a monthly BRL cap per project from the dashboard. Once month-to-date production spend reaches the cap, every send path refuses new work with 402 spend_limit_exceeded until the next calendar month rolls over — or you raise the cap: POST /v1/messages, POST /v1/batches, the MCP send and broadcast tools, and dashboard sends and broadcasts. A running broadcast stops before its next page of recipients and emits message_batch.failed with error_message: "spend_limit_exceeded"; an automation message step fails its run with the same code. A spend_limit.hit webhook fires on the crossing, unless a rental fee or a payment fee caused it. The cap limits what you send; it does not stop the monthly rental fee of a number Tyxter provisions for you, which is charged regardless and counts toward the spend of the month its ledger line is dated in (see How number rental is billed). It does not refuse a payment creation either, and payment fees count toward month-to-date spend (see Payment fees).

Low-balance alerts

When the balance crosses the configured threshold downward (default R$10), a credit.low_balance webhook fires exactly once per decrement that caused the crossing. Subscribe to it to auto-top-up.

Invoices

GET/v1/invoices
GET/v1/invoices/{id}/download

Monthly CSV roll-up per project. BuildInvoiceUseCase is idempotent on (project_id, period_start); the download URL is a 15-minute presigned S3 GET.

For a per-phone read, poll GET /v1/phone-numbers and GET /v1/phone-numbers/{id} with phone_numbers:read, including while credit is exhausted. Their renewal field reports the current month: the next charge on the 1st, whether the month is unpaid with the recommended action, and on the free plan when an unpaid number is released (see How number rental is billed). The renewal field can report at_risk while status is active. The Billing page joins that shared current assessment to recorded history by scoped phone ID; loading or missing current data is never treated as healthy. See the phone-number guide for all-page polling and recovery without email.