Young's Mind
Decisions

WhatsApp metering — independent re-verification

Card t_c2f6df57 is the board-mirror of the WhatsApp metering card. The ruling was landed mid-flight by the twin card t_1d1257c3 (commit 0b6fdc7, 22:30), inside this run. So this card's job was not to write the ruling — it was to independently verify it against primary sources, and correct what is wrong.

WhatsApp metering — independent re-verification

Card t_c2f6df57 is the board-mirror of the WhatsApp metering card. The ruling was landed mid-flight by the twin card t_1d1257c3 (commit 0b6fdc7, 22:30), inside this run. So this card's job was not to write the ruling — it was to independently verify it against primary sources, and correct what is wrong.

Verdict: the ruling stands. Two defects found and corrected, plus one gap closed. The A$49 line, the 150-message allowance, the hybrid model and the Tech-Provider default all survive. The corrections are to how the overage rate is computed and controlled, not to the model.


1. What I verified, and how

Every load-bearing claim re-fetched from the primary source in this run, not from the twin card's text.

#ClaimMethodResult
1AU is in the Rest of Asia Pacific region, not a standalone marketMeta pricing page, "Pricing regions on the rate card" — full 16-market list read✅ confirmed (AF, AU, KH, CN, JP, LA, MN, NZ, PG, PH, TW, TJ, TH, TM, UZ, VN)
2RoAP marketing = A$0.1095, utility/auth/service = A$0.0148Re-downloaded Meta's AUD list-rate card (HTTP 200) → sha256 d874292c… → parsed the xlsx directly✅ confirmed — sha256 matches the twin card's recorded upstream file exactly; 47 market rows, RoAP row identical to the committed CSV
3Marketing has no volume tier at any volumeRe-downloaded Meta's AUD volume-tier card (HTTP 200) → sha256 1d809ad7… → parsed✅ confirmed — the card's own header: "Volume tiers apply only to utility and authentication messages"
4RoAP marketing increased 1 Oct 2026Meta's Oct-2026 change table on the pricing page✅ confirmed — "Rest of Asia Pacific · Marketing · Increase"
51 month notice for a rate-card update; 4×/yrMeta's "Minimum advanced notice" table✅ confirmed — rate card update = 1 month; model change = 6 months; pricing model add-on = 3 months
6Service messages became chargeable 1 Oct 2026; 1,000 free/phone number/moMeta's "Charging for messages that were previously free"✅ confirmed — and the utility-in-CSW pricing.type changed free_customer_service → regular on 1 Oct 2026
7Meta charges only on deliveryMeta pricing page✅ confirmed — "Businesses are only charged when a message is delivered"
8Bill To Party liability (Solution Partner)Meta — Managing credit lines, live✅ confirmed verbatim — "You are liable for and will pay Meta for all WhatsApp Business Platform spend made by these businesses."
9No reselling of the platformMeta — Meta Terms for the WhatsApp Business Platform §4.1(c)✅ confirmed — "distribute, sell, resell, or rent the WhatsApp Business Platform to third parties"
10FIXED credit partition with an amountGraph API — Extended Credit Allocation Config✅ confirmed — partition_type enum {FIXED, AUTH, FIXED_WITHOUT_PARTITION}; amount set only when type is FIXED
11Messaging limit tiers TIER_250 → 2,000 → 10,000 → 100,000 → UnlimitedMeta — Messaging Limits, live✅ confirmed — and per business portfolio, shared by all numbers in it
12AI-Provider clause: AU is not on the charged listMeta — New pricing policy for AI Providers (updated 15 Oct 2026)✅ confirmed — charged markets are Italy, Brazil, Türkiye + the EU-27 list (charged to 12 May 2026, not charged since)
13EVE is a business-CS agent, not a general-purpose assistantWhatsApp Business Solution Terms + TechCrunch (Meta's own confirmation)✅ supported — Meta: "this move doesn't affect businesses that are using AI to serve customers on WhatsApp". A reading, not a legal opinion — twin card's open item 4 stands

Re-derived independently: 49 ÷ 0.1095 = 447 break-even · 49 × 0.4 ÷ 0.1095 = 179 for 60% margin · 150 × 0.1095 = A$16.43 → 66.5% margin on the A$49 line. All three match the twin card's numbers exactly. I also re-ran wa_metering_model_2026-10-20.py — it executes, exit 0, and reproduces its own table.


2. 🔴 Defect 1 — the bid_amount figure was wrong by 100×

The landed ruling (§5.4, control 2) said:

set bid_amount to our own billed rate (A$0.1314 → bid_amount 131 per 1,000 deliveries in the account currency's smallest unit)

Meta's own unit definition (from Set a max price for marketing messages (BETA), "Calculating max price amounts"):

To set a max price of $0.05 USD per delivery: Set bid_amount to 5000.

i.e. bid_amount = per-delivery price × 1000 × 100 — the account currency's smallest unit, which for AUD is cents.

0.1314 × 1000 × 100 = 13140      <- correct
0.1314 × 1000       = 131        <- what the ruling said

Why it matters: bid_amount 131 buys A$0.00131 per delivery — a cap 100× below the A$0.1314 we bill. Control 2 exists to make the spread non-negative; as written it would have capped our deliveries at a hundredth of cost, i.e. it protects nothing. A control that reads as protection in the design of record and is not is worse than no control.

The metering script carried the identical error (§9 printed round(MKT*MARKUP*1000) = 131). Both are fixed; the script now prints 13140 and shows the derivation.

Also confirmed while I was there: bid_strategy must be LOWEST_COST_WITH_BID_CAP whenever bid_amount is set, and a bid cap is a price cap, not a budget — it does not stop volume. So controls 1 (HIL gate) and 3 (FIXED partition) are load-bearing, not decorative.


3. 🔴 Defect 2 — A$0.1314 is the AU overage rate, and the ruling never said so

This is the more consequential of the two, and it is a gap, not a typo.

Meta charges by the recipient's country calling code. A$0.1314 is A$0.1095 (RoAP) × 1.20 — correct for Australian recipients. The ruling quoted it as the overage rate in §5.2, in §5.3's worked example, and in the tenant contract terms (§5.5 clause 2). A tenant's audience is not necessarily Australian. From the rate card I re-parsed live:

Recipient marketMeta marketing costWe bill (AU rate)Effect on us
NetherlandsA$0.2077A$0.1314🔴 we lose A$0.0763/msg — A$76.30 per 1,000
GermanyA$0.1775A$0.1314🔴 we lose A$0.0461/msg — A$46.10 per 1,000
ChileA$0.1156A$0.1314ok (+A$0.0158)
Rest of Asia Pacific (AU)A$0.1095A$0.1314✅ our designed 20% markup
ColombiaA$0.0163A$0.1314🟠 overcharge A$0.1151/msg (706%)
IndiaA$0.0153A$0.1314🟠 overcharge A$0.1161/msg (759%)
TurkeyA$0.0142A$0.1314🟠 overcharge A$0.1172/msg (825%)

Two failure modes, both real. (a) A blast to Netherlands recipients costs us A$76.30 per 1,000 messages more than we bill — the exact loss control 2 was supposed to prevent, and control 2 only helps if the cap is set to the recipient's market rate. (b) A tenant with an Indian or Turkish audience is overcharged up to 8× on the overage line — a pricing-dispute and reputational risk, not a margin.

The good news: the meter already has the field. Meta's pricing_analytics edge breaks charges down by COUNTRY × PRICING_CATEGORY × PRICING_TYPE (dimensions COUNTRY, PHONE, PRICING_CATEGORY, PRICING_TYPE, TIER), and the status-message webhook gives pricing.category per delivery. The market is knowable per delivery — we simply were not pricing on it.

What changed: the billing rule is now overage_rate(recipient_country) = Meta marketing rate(country) × 1.20. For AU tenants that is A$0.1314, unchanged. The A$49 line, the 150 allowance and the hybrid model are untouched. §5.5 clause 2 now says "for Australian recipients" and a new clause 6 puts the recipient-market rule in front of the tenant. Two open items added (per-country bid_amount via bid_country_multiplier_overrides; and the product decision on whether we bill per-market or a single blended rate).


4. What I did not change, and why

  • The A$49 line price — set by the sibling card t_b2496986; the twin card's ruling kept it, and nothing I verified argues against it.
  • The 150-message allowance — inside the ≤179 envelope; still a judgment (twin card's open item 6: re-baseline from pilot data).
  • The hybrid model — the reasoning survives: a pure pass-through makes the A$49 line meaningless; a pure allowance at ≤179 is "less than one campaign".
  • The Tech-Provider default — reinforced, if anything, by §4.1 below.

5. 🟡 One structural gap I found that the twin card did not name

Under the twin card's Shape A (tenant owns the WABA, tenant pays Meta), our allowance is enforced in our product, not in Meta's billing — the twin card says this and is right. But it understates one consequence:

Meta's messaging limit is set at the business portfolio level and is shared by all phone numbers in it (Meta — Messaging Limits, live: "Messaging limits are calculated and set at the business portfolio level and are shared by all business phone numbers within a portfolio"). New portfolios start at 250 unique users per 24h outside a customer-service window.

So:

  • Under Shape A the tenant's own portfolio carries the limit — our commercial allowance (150) is below Meta's (250), so our cap is the binding one. Fine.
  • Under Shape B, if tenants' WABAs are attached to our credit line, the portfolio that carries the messaging limit is the one that owns the numbers. If that portfolio is ours, one tenant's blast can consume the portfolio's limit and starve every other tenant — Meta's own words: "it is possible for one number to consume all of the portfolio's messaging capability within a given period."

This is a capacity-planning constraint on Shape B that the twin card did not name, and it sits alongside its (correct) FIXED-partition caveat: a credit partition caps spend; the messaging limit caps reach; they are different ceilings and both are needed. Added to the open-items list.

Also recorded: Meta's pricing_analytics does not return COST for Messaging accounts that share a Solution Partner's credit line ("If your Messaging account shares a Solution Partner's credit line, reach out to your Solution Partner to understand your charges"). Under Shape B we would therefore be billing from our own credit line rather than from a tenant-side analytics read — a real operational difference between the two shapes, and another reason Shape A is the default.


6. Corrections applied (files)

FileChange
whatsapp-cost-metering-model-2026-10-20.md§5.2 table: overage rate marked AU-only; §5.4 control 2: bid_amount 131 → 13140; two dated correction notes (defect 1, defect 2); §5.5 clauses 2 and 6 (recipient-market rule); §7 open items 8 and 9 added
wa_metering_model_2026-10-20.py§9 bid_amount fix + unit derivation + "a bid cap is not a budget"; new §10 market-aware overage table; §10 verdict logic corrected (it compared market rates to each other instead of to the single billed rate)

Both re-probed after the edit: the script runs, exit 0, and its §10 numbers match an independent cross-check against the committed rate card (Netherlands −A$0.0763, Germany −A$0.0461, AU +A$0.0219, India +A$0.1161, Turkey +A$0.1172 — identical to the table in §3 above).


7. Honest limits of this verification

  • Nothing was tested against a live Meta account. Every rate is from Meta's published rate cards and terms, downloaded and parsed in this run. The rates are evidence; the behaviour is not.
  • I did not obtain our own credit line, so Shape B's terms are unknown.
  • GST treatment of Meta's fees is unresolved (twin card's open item 3) — a ~10% swing on the largest variable cost.
  • The AI-Provider clause remains a reading, not a legal opinion (twin card's open item 4). TechCrunch corroborates Meta's own statement that business-CS bots are unaffected, but that is a press statement, not the operative clause read by a lawyer.
  • The marketing_lite rate card is still unverified (twin card's open item 5) — and note the AUD list-rate card I re-parsed has no marketing_lite column at all, which is direct evidence that the Cloud-API marketing rate and the MM-API marketing rate are not the same published figure. The Cloud API marketing sunset is 13 Oct 2027; new Messaging accounts cannot use Cloud API marketing from 13 Apr 2027.
  • I did not verify the FIXED-partition exhaustion behaviour — the twin card's open item 1, still Sol's, still blocking Shape B.
  • The 150-message allowance remains a judgment, not a derived optimum.

8. Net effect on the card's mandate

The card asked for the allowance-vs-passthrough ruling before the Social add-on GA quote. That ruling exists and stands: hybrid — A$49 WhatsApp platform line including 150 delivered marketing messages/tenant/month, then metered overage at cost + 20%, sold separately from the Social add-on, with the Tech-Provider shape as the default because we cannot be the Bill To Party for tenants' Meta spend without carrying their liability.

The GA quote is unblocked — with two corrections applied first, and with the overage rate now correctly specified as recipient-market + 20%.

But the quote should not go out before: the market-aware overage rate is built (open item 8), the tenant-facing rate presentation is decided (open item 9), and Young's accountant has answered the GST question (open item 3). A rate we cannot invoice correctly is not a quote.

— mira

Copyright © 2026