Skip to main content

The WhatsApp WABA lifecycle — connect, register, migrate, disconnect

A WhatsApp Business Account (WABA) is a Meta-side object: one account under a Meta Business Manager, owning one or more phone numbers, graded by Meta for quality, and metered for sends. On Devotel Orbit, a WABA becomes a connection — a tenant-scoped record that carries the credentials, the registered phone numbers, and the onboarding state. This page describes the lifecycle of that connection end to end: how it attaches, what state it moves through, what a migration from another Business Solution Provider (BSP) carries, and how it detaches. The step-by-step setup walkthrough is Set up your first WABA; the field-level WhatsApp surface is on the WhatsApp channel page.

What a WABA is on Orbit

A WABA belongs to a Meta Business Manager, not to Orbit. Orbit never owns the WABA — it holds the credentials a tenant authorizes Orbit to use on the tenant’s behalf, and it reads and sends through Meta’s Graph API with those credentials. The binding is one WABA per Meta Business Manager tenant, attached to one Orbit organization at the end of Embedded Signup. Embedded Signup is Meta’s in-browser authorization flow. The tenant completes it inside the dashboard; when it finishes, Meta hands back four things that Orbit stores against the connection:
  • A Graph API access token — used for every subsequent send, template, and health read against that WABA.
  • The WABA id — the Meta Business Account identifier, used to scope template management, quality reads, and webhook routing.
  • A phone-number id — the first phone number attached to the WABA, used as the default sender until additional numbers are registered.
  • A webhook subscription — the WABA is subscribed to the messages and related webhook fields so inbound replies and lifecycle events reach Orbit.
The connection row carries a config_id — the Embedded Signup configuration id Meta uses to scope the flow — and an app_id, both stamped at creation. The access token is stored encrypted; every read that needs it decrypts it on demand, and the token is redacted on every list/projection response. A tenant can hold more than one WABA connection at once (multi-WABA); each is an independent connection with its own token, phone numbers, and health.

Lifecycle states

A WhatsApp connection moves through a small state machine. The fields that matter at each step are status, registered_at, and config_id — the last is stamped at creation and never changes, the first two advance as the connection matures. The connected status does not by itself mean “can send.” A connection is send-ready only once registered_at is stamped — that is, once at least one phone number has completed registration with Meta. The distinction exists because Embedded Signup returns the phone-number id before the number is registered, and the dashboard surfaces the intermediate state so an operator can see “connected, register a number to start sending” instead of a silent gap.
After Embedded Signup completes, the connection’s send status reads as pending_verification until a phone number is registered. Sends against an unregistered connection refuse up front with 422 CHANNEL_NOT_CONFIGURED — before a message row is written. Register a number and the same send passes; nothing about your send code changes.
Registration is the act of telling Meta, for a given phone-number id on the WABA, that this number is now in service for business messaging. It is a per-number operation, not a per-WABA one — which is why a WABA can be connected without being send-ready, and why attaching a second number later does not re-open the first.

The three send paths of history

WhatsApp send traffic on Orbit has run over three different paths over the platform’s lifetime. Today only one of them carries tenant sends; the other two are narrowed to operator-side use or removed entirely.
  • Tenant WABA (the live path). The tenant’s own WABA, connected through Embedded Signup. Sends resolve the tenant’s stored credentials at send time and go out under the tenant’s own phone number. This is the only path tenant send traffic rides today.
  • Platform WABA (operator-side only). Orbit’s own platform-owned WABA, configured with DEVOTEL_WHATSAPP_ACCESS_TOKEN, DEVOTEL_WHATSAPP_PHONE_NUMBER_ID, and DEVOTEL_WHATSAPP_BUSINESS_ACCOUNT_ID. It is used only for platform-initiated operations — template management and WhatsApp Calling registration — never for carrying a tenant’s message traffic. When the access token is unset at boot, the platform provider is not registered and only per-tenant connections resolve.
  • Shared demo WABA (retired 2026-10-08). A shared Devotel-owned test account that used to carry real sends for organizations that had not yet connected their own WABA. That path was removed on 2026-10-08: there is no longer any send that rides the platform WABA on a tenant’s behalf. Send endpoints now refuse up front with 422 CHANNEL_NOT_CONFIGURED when no tenant WABA is connected, the retired demo-account endpoints answer 410 GONE, and GET /whatsapp/get-status renders retired: true / verified: false for a previously verified organization so legacy dashboards show a coherent “connect your own account” state instead of erroring.
The retirement is absolute: there is no admin override or fallback that routes a tenant send onto the platform WABA. Connect your own WABA and the same send calls pass.

Number attach and reassignment

A WABA owns one or more phone numbers; Orbit registers and sends against one phone number at a time. The connection stores a default_phone_number_id, and a send that does not specify a sender resolves to that default. Additional phone numbers can be attached to the same WABA and registered independently — each is its own registration call to Meta, and each carries its own quality rating from Meta. The send-time binding is the phone number, not the WABA. A send resolves the phone-number id to use (the explicit one on the request, or the connection default), and that number’s quality rating and messaging-limit tier govern the send. Reassigning the default number on a connection changes which number an unspecified send goes out from, but does not change which WABA owns it — the WABA is the credential scope; the phone number is the send identity. This is why a single WABA can carry numbers with divergent quality ratings: Meta grades per number, and the send path honors the per-number verdict. Per-number verification (the Meta registration step) is what moves a number from “attached but not send-ready” to “send-ready.” A number that is attached but not yet registered behaves like the unregistered-connection case above: sends targeting it refuse with 422 CHANNEL_NOT_CONFIGURED until registration completes. The dashboard surfaces the per-number registration state so an operator can see which numbers on a WABA are live and which are pending.

Migration from another BSP

Moving a WABA from another BSP (Infobip, Twilio, Vonage, MessageBird, 360dialog, or Meta Cloud API directly) to Orbit is a managed Meta process, not an Orbit-internal one. The full step-by-step runbook — release from the source BSP, assign Orbit as the new partner, sync templates, point webhooks — is on BSP Transfer / Number Porting. The model-level summary of what moves and what does not: What moves with the WABA:
  • The WABA id — the Meta Business Account identifier. It is the same object on Meta’s side; only the BSP attached to it changes.
  • The phone-number id(s) — the numbers stay on the WABA. You do not re-provision numbers.
  • The verified quality rating — in most cases Meta carries the Green/Medium/Red phone-level rating across the BSP change.
  • The messaging-limit tier — the 1K/10K/… tier Meta assigns to the WABA. It usually carries over.
  • Approved templates — Meta keeps the templates on the WABA; they are not re-approved.
What does not move:
  • Message history. WhatsApp stores messages on Meta’s side for 30 days only, and the conversation metadata that ties a message to a BSP is BSP-scoped. Orbit cannot see the prior BSP’s conversation history; the conversation record starts fresh on Orbit once the WABA is attached and sends resume.
  • Template analytics from the old BSP. Sent/delivered/read counts are BSP-scoped and reset to zero on Orbit, even though the templates themselves carry over.
  • Webhook delivery logs from the old BSP. Those stay on the prior BSP’s system.
  • Templates that were never approved on the old BSP. Unapproved drafts do not exist at Meta, so there is nothing to carry.
Outbound sending is paused for the migration window — typically under 15 minutes, up to a few hours depending on how quickly the releasing BSP releases. After the WABA is attached and templates are synced, run a single test send to an internal number to confirm the path; quality rating is worth watching for the first 24 hours, because the first post-migration blast can downgrade a Green rating to Medium if it triggers recipient blocks. For the failure modes that arise during a migration — a release that stalls, a template sync that comes back empty, a quality downgrade on the first send — see Troubleshooting: WhatsApp migration.

Disconnect and delete

A WABA connection can be disconnected and, ultimately, deleted. The two are distinct transitions:
  • Disconnect clears the stored credentials on the Orbit side (the access token, the phone-number ids) and flips status to disconnected. It does not delete the WABA on Meta’s side — the WABA continues to exist in Meta Business Manager, unattached to Orbit, and can be re-attached to this or another BSP later. On Orbit, a disconnect leaves the conversation and message history rows in the tenant schema intact; the history is not torn down when the credentials are. This is so an operator who disconnects by mistake, or who is mid-migration, does not lose the audit trail of what was sent.
  • Delete is the terminal teardown: the connection row is removed and the tenant-schema history it pointed at is handled per the tenant’s retention policy. A delete is irreversible on the Orbit side.
The tenant write that handles a disconnect is the dashboard’s disconnect action or the corresponding API call; the tenant write that handles a delete is the organization-level teardown path. Neither touches the WABA on Meta’s side — deleting the Orbit connection does not delete the Meta object, and re-attaching the same WABA later through Embedded Signup produces a fresh connection row that points at the same Meta WABA id.

Conversation pricing hooks

WhatsApp charges per conversation, not per message — a conversation is a 24-hour window opened by the first message in a category (marketing, utility, authentication, or service), and every message inside that window is billed against the one conversation. Orbit’s billing model hooks into this at send time: when a send opens a new conversation category for a recipient, the conversation-category and the 24-hour window are stamped on the send, and the per-conversation price is what the wallet ledger records. The price fields that appear in the ledger are the resolved per-conversation rate for the category and country of the recipient, plus any surcharges the rate card applies. The full billing model — how a conversation category is resolved, how the 24-hour window opens and closes, and how the wallet meter records a conversation versus a message — is on Billing and wallet and the usage metering pipeline; the WhatsApp-specific rate fields are on the WhatsApp pricing guide. The model that decides whether an off-window send is allowed at all — the free-form session vs template rule — is on Messaging windows and off-window sends.

See also