OmnioChat
← All posts

Getting Meta App Review right for a messaging product

By Super Admin

Meta App Review is the gate between a working integration and a product anyone can use. Until you pass it, your app works for people who hold a role on it and for nobody else — which means it looks finished right up until your first customer.

We have been through it twice: once for WhatsApp, once for ten permissions across Messenger, Instagram and publishing. This is what we would tell ourselves at the start.

Submit in batches, but batch deliberately

Permissions are assessed individually. There is no penalty for submitting more than once — no rate limit, no black mark.

What a single large submission costs you is time: nothing ships until the slowest item is demonstrable, and a reviewer who cannot complete one flow tends to return the whole submission rather than approving around it.

Our first submission was WhatsApp alone and came back in nine days. The second batched ten items that could all be shown from one test account in one sitting. The rule we settled on: batch what shares a demonstration, split what doesn't.

One real trap here. We prepared a submission intending seven permissions and sent three, because adding a permission to a use case is not the same as adding it to the request. The tell is in the dashboard — a permission reads Ready for testing rather than Pending App Review, and its API call counter sits at zero. A permission's review state is app-level, so "Ready for testing" anywhere means it is under review nowhere. We did not notice for a week.

The API call counter is a gate, not a hint

Several permissions show 0 of 1 API call(s) required. Meta checks its own call log; you cannot assert your way past it. The call has to have actually happened, from your app, recently.

This shapes the order of work. For each permission, find the single user action that produces its call, and do that action on production before you fill in the form. Connecting an account, publishing a post, sending a reply — the same run usually produces the call and the screencast, so do it once with the recorder on.

Counters can lag. Ours moved within minutes most times and took longer once. The panel says 24 hours; plan for that and be pleasantly surprised.

What each screencast must show

Meta's general guidance is loose; the per-permission pages are specific, and the per-permission pages win. Read the reference page for every permission you are requesting.

Things that caught us:

One clip per permission. Meta's solution-provider guidance says a submission "may be rejected if you highlight multiple permissions being used as part of the same video." In practice, permissions that genuinely co-occur in one flow — the Page picker demonstrates pages_show_list and pages_read_engagement simultaneously — are fine from one recording. Messaging and publishing in one video are not.

The login grant is usually required. Several reference pages ask the clip to show the Facebook Login flow including the permission being granted. That is a problem once your own account has already granted it: Meta skips the dialog and you cannot film what no longer happens. Facebook Login for Business shows an "Edit settings" option on its re-consent screen — that is the way back to the picker, and it is better than revoking the app, which drops every token that grant issued.

Record against production, logged in, with the URL bar visible. A reviewer who sees localhost rejects on sight.

Keep the send and the arrival in one unbroken take. A cut between "reply sent" and "reply received" is the thing that reads as a mock.

The requirements that are not permissions

Two things we nearly submitted without, both filed under Features rather than Permissions:

Human Agent, which allows a human to reply up to seven days after the customer's message instead of 24 hours. If your product is a staffed inbox rather than a bot, you need this and it is easy to miss because it is not in the permissions list.

Business Asset User Profile Access, which is what lets you read the name and picture of someone who messaged the business. Without it, every conversation is titled with a sixteen-digit ID. Worse, it fails in the quietest possible way: the lookup is refused, your code falls back to the raw ID, and because features at Standard Access work for anyone with a role on your app, the names appear perfectly during your own testing and vanish for customers.

Test accounts: the distinction that matters

For pages_messaging, Meta's form says plainly: create a real Facebook account and grant it the Tester role. Do not submit a test user created in App Roles — those synthetic accounts cannot send or receive Messenger messages.

This matters beyond the paperwork. Before approval, Meta only delivers messages from accounts holding a role on your app. A reviewer messaging your Page from their own account gets silence. So the test account you supply is not a formality; it is the only way the reviewer can reproduce anything.

Do not supply your own personal Facebook login. It is not scoped: whoever holds it can change your app settings, remove admins, and reach the business portfolio that owns your WhatsApp account. Create a separate real account, grant it Tester, and share that.

Write the instructions for someone who has never seen your product

The reproduction steps are where a submission is won or lost. Meta's example template assumes a bot with a menu and a webview. If your product is a human inbox, a reviewer following that template will look for a Get Started button, not find one, and conclude the integration is broken.

Say what it is, plainly, at the top. Ours ends with:

OmnioChat is a human-staffed shared team inbox, not a bot. There is no automated menu, Get Started flow or CTA buttons — replies are typed by the business's own staff.

Then number the steps so literally that a stranger can follow them without judgement calls, and make each one self-contained. If step 2 says "message the Page", put the link and the account credentials in step 2, not in a different tab.

Handling the parts you cannot demonstrate

Some things genuinely cannot be shown before approval, because approval is what enables them. Do not hide that — explain it, show what you can, and say what the reviewer is looking at instead.

For unsent messages — Meta asks Instagram messaging apps to demonstrate how they handle a customer withdrawing a message — we had to build the feature first, because what we had was the bug: the original stayed and a blank bubble appeared beneath it. Which is a reasonable summary of the whole process. App Review is tedious, but every requirement we found annoying turned out to describe something our product actually did badly.


Written while getting OmnioChat through two submissions. If you are in the middle of one, the dashboard's API call counters are the most honest signal it gives you — they are the one thing that cannot be argued with.