The Meta integration hierarchy: Portfolio, App, WABA, Number, Token

Five pieces that all have to line up before a single message can send, and the one mental model that makes every confusing Meta error message make sense once you have it.

Beginner

4 min read

The hierarchy, laid out

Business Portfolio
│  the top-level container: the company account itself
│
├── Meta App
│     a technical registration/credential container.
│     Holds: App ID, App Secret, webhook URL, "WhatsApp" added as a Product.
│     NOT the product being built — just Meta's side of the integration.
│
├── WhatsApp Business Account (WABA)
│     holds: message templates, all of them, per language
│     connects to one or more Apps for actually sending
│     │
│     └── Phone Number(s)
│           the real sending number. Has its own Phone Number ID —
│           this is the value every API call's URL is built around.
│
├── System User
│     a non-human identity that holds the permanent access token,
│     granted permission on specific Apps + specific WABAs
│
└── People
      human admins — approve sensitive actions, manage billing,
      grant/revoke access

Nearly every confusing moment in a first integration comes from not knowing which of these similarly-named things actually holds what. Once this diagram is internalized, most of Meta's error messages stop being mysterious.

The key relationships to memorize

  • A Business Portfolio can own multiple Apps and multiple WABAs.
  • One App can connect to multiple WABAs (and, less commonly, vice versa).
  • One WABA can hold multiple phone numbers.
  • Templates belong to the WABA — not the App, not the Business Portfolio.
  • Webhooks belong to the App — not the WABA. One App's single webhook URL receives events for every phone number connected to it; each event payload includes which phone number it's about, so the receiving code can tell them apart.
  • The access token belongs to a System User, scoped to whichever Apps/WABAs it was explicitly granted permission on at creation time.

Why "templates belong to the WABA" matters in practice

This is the single most common real-world mistake: submitting a message template while testing under one WABA (often a temporary test account created during initial setup), then expecting it to be available once sending switches to the real, production WABA. It won't be there. Templates don't travel between WABAs, even ones owned by the same Business Portfolio and connected to the same App. Always confirm which WABA a template is actually being submitted under before assuming it will "just work" later.

Why "webhooks belong to the App" is actually convenient

Because one App's webhook receives inbound events for every phone number connected to it, adding a second phone number to the same App doesn't mean standing up a second server endpoint. The event payload's phone-number identifier is what a receiving system uses to route an inbound message to the right internal logic — one webhook, many numbers, a single field doing the disambiguation.

Can the same App be reused for a second, unrelated project?

Mostly yes, and this is worth internalizing before assuming a from-scratch setup is required every time:

  • Reuse the App itself — there's rarely a reason to create a second Meta App. An App that already has WhatsApp added as a Product, with its webhook already configured, can connect to additional WABAs and phone numbers as needed.
  • Reuse the WABA and phone number, if the new use case doesn't need to present as a visibly different business identity to its own customers — it just submits its own templates under the existing WABA.
  • Register a new phone number (same App, same Business Portfolio) only when the new use case genuinely needs its own visible identity — a different display name shown to its own customers.
  • The one thing that doesn't automatically carry over: a System User's access token is scoped to specific assets at creation time. Adding a new WABA or phone number later means checking whether the token already covers it, or whether the System User's permissions need extending — a permissions edit, not a full token regeneration, but an easy step to forget.

A genuinely hard limit, not a preference

An unverified Business Portfolio has a hard cap on how many WABAs it can hold. This has nothing to do with Apps, code, or templates — it's purely an account-level constraint. It only becomes relevant if a Portfolio wants many separate WABAs; reusing one WABA across multiple projects/phone numbers, as recommended above, avoids ever hitting it. Business Verification (a later lesson) is what lifts this cap.

Further reading

Check your understanding

A quick comprehension check — not tracked, not graded, just for you.

1. A team submits a message template while testing under a temporary test WABA, then switches to the real production WABA. What happens to that template?

2. An App has two phone numbers connected to it. How many webhook URLs need to be configured?

3. A new phone number is added to an existing WABA. The existing permanent access token starts returning permission-denied errors for that number. What's the most likely cause?

4. What is the actual constraint an unverified Business Portfolio hits when trying to create several separate WABAs?