> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gateway.connexease.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pricing Table

> Current Meta template rates by market and category, read live from the public pricing feed.

Meta template fees in **USD per delivered message**. The market is derived from the recipient's phone number country code — see [Meta Fee](/essentials/billing/meta-fee) for the full country mapping.

export const LivePricingTable = ({rates, meta}) => {
  const [state, setState] = useState({
    status: 'loading'
  });
  useEffect(() => {
    let cancelled = false;
    Promise.all([fetch(rates).then(res => {
      if (!res.ok) throw new Error('HTTP ' + res.status);
      return res.json();
    }), fetch(meta).then(res => res.ok ? res.json() : null).catch(() => null)]).then(([data, info]) => {
      if (!cancelled) setState({
        status: 'ready',
        data,
        info
      });
    }).catch(err => {
      if (!cancelled) setState({
        status: 'error',
        message: err.message
      });
    });
    return () => {
      cancelled = true;
    };
  }, [rates, meta]);
  if (state.status === 'loading') return <p>Loading rates…</p>;
  if (state.status === 'error') return <p>
        Could not load the current rates ({state.message}). Please try again, or contact
        gateway@connexease.com if the problem persists.
      </p>;
  const money = v => '$' + v.toFixed(4);
  const optional = v => v > 0 ? money(v) : '—';
  const day = iso => new Date(iso).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  });
  const info = state.info;
  const upcoming = info && info.upcoming && info.upcoming.length ? info.upcoming[0] : null;
  return <>
      {info && info.effective_from && <p>
          <strong>Effective {day(info.effective_from)}</strong>
          {info.last_checked_at ? ` · last verified ${day(info.last_checked_at)}` : ''}
        </p>}

      <table>
        <thead>
          <tr>
            <th>Market</th>
            <th>Marketing</th>
            <th>Utility</th>
            <th>Authentication</th>
            <th>Authentication — International</th>
            <th>Service</th>
          </tr>
        </thead>
        <tbody>
          {Object.entries(state.data).map(([market, r]) => <tr key={market}>
              <td>{market === 'OTH' ? 'Other' : market}</td>
              <td>{money(r.MARKETING)}</td>
              <td>{money(r.UTILITY)}</td>
              <td>{money(r.AUTHENTICATION)}</td>
              <td>{optional(r.AUTHENTICATION_INTERNATIONAL)}</td>
              <td>{money(r.SERVICE)}</td>
            </tr>)}
        </tbody>
      </table>

      {upcoming && <p>
          A new rate card takes effect on <strong>{day(upcoming.effective_from)}</strong>
          {upcoming.markets ? `, covering ${upcoming.markets} markets` : ''}. Meta publishes the new
          rates shortly before they apply; this table switches over automatically on the effective
          date.
        </p>}
    </>;
};

<LivePricingTable rates="https://storage.googleapis.com/connexease-public-pricing/whatsapp/pricing.json" meta="https://storage.googleapis.com/connexease-public-pricing/whatsapp/pricing.meta.json" />

A dash means no separate rate applies for that market.

Markets not listed individually fall into the regional group covering them — `Rest of Western Europe`, `Rest of Asia Pacific`, and so on. Anything outside every listed group is billed at the `Other` rate.

<Note>
  This table is read live from a machine-readable feed, so it always reflects the current rate card. If you are building billing logic, read the feed directly rather than scraping this page — available as [JSON](https://storage.googleapis.com/connexease-public-pricing/whatsapp/pricing.json) or [CSV](https://storage.googleapis.com/connexease-public-pricing/whatsapp/pricing.csv).
</Note>
