Vorluno
ServicesniikoProcessChangelog
Get niiko

engineering notes

Running our own WhatsApp number without waiting for App Review

2026-07-15 · Vorluno

The typical bottleneck for a WhatsApp agent is well known: Meta's Advanced Access review can take days to weeks, and most teams treat it as the gate that has to clear before anything can go live. niiko's embedded signup flow — the one that lets an agency onboard its own clients' WhatsApp numbers — does sit behind exactly that review, submitted and still pending as of this writing. But that review governs one specific case, and it is not the only way to connect a number.

For a business connecting its own number — not a client's — Meta's Cloud API only needs standard access and a system user token issued from the business portfolio: no embedded signup, no app review, no waiting. niiko shipped that path directly: an "advanced — connect with token" option that reuses the same channel-finalization logic — derive assets, subscribe, register, verify — that the reviewed signup flow uses once a token is in hand. The one wrinkle: Meta's token-inspection endpoint could not reliably resolve which WhatsApp Business Account an ambiguous token belonged to, so the connection flow takes the account and phone number identifiers explicitly instead of relying on auto-discovery.

With the number connected, the other half went in — inbound webhook, agent, reply — end to end, and it has run in production against Vorluno's own number since the number was first connected: a contact messages it, the agent reads the message, qualifies the lead, and escalates or replies through the same pipeline described in the notes above.

Getting there surfaced eight separate bugs that only exist once a real number is sending and receiving real traffic — none of them showed up against a sandbox. A dead code path crashed the settings page in production because the production bundler treats a re-exported TypeScript type from a server-action file as a live runtime binding. A queued reply went out with no body because the enqueue call never attached its text. An escalation tried to notify a free-text name instead of a user identifier and failed a database constraint. A qualification script and its canned answers were built but never actually reached the model's prompt. A confidence field's declared numeric range tripped a structured-output rejection at the model provider. A stuck job in the queue silently deduplicated every new conversation turn behind it. Sender selection fell back to the wrong number when the connected number's WhatsApp category did not match the message's purpose. And a successful send never got written to the conversation view, so a reply that went out over WhatsApp looked like it had never been sent.

None of those eight bugs are exotic, and that is the point: they were latent in code that had never been exercised against a real API, real timing and real edge cases. A sandbox and a set of unit tests could not have found most of them. The honest lesson is not "connect your own number early" as a growth hack — it is that running the real integration against your own number, before a single customer touches it, finds the bugs a mock never thinks to simulate.

← All notes

Vorluno

A software studio in Panamá, shipping in English worldwide. The team behind niiko.

Product

  • niiko
  • Modules
  • Changelog
  • Roadmap

Developers

  • Engineering notes
  • Documentation
  • Status soon

Company

  • Services
  • Embedded team
  • Process
  • About
  • Tools
  • Contact
© 2026 Vorluno · Panamá · Privacy · Terms// shipped, not staged.