Your permission was approved. The call still fails.
App Review passed. The scope is granted. The token is valid and unexpired. And the Graph API still returns an error that reads like a permission problem. In most of these cases the permission is fine — what is missing is business asset access, a second and entirely separate check that Meta runs on the identity behind the token.
This is one of the most expensive misdiagnoses in Meta integration work, because every symptom points developers back at the OAuth layer they already fixed. Teams re-request scopes, re-run App Review, regenerate tokens, and re-read the permissions reference — while the real blocker sits in Business Settings, where an asset was never assigned to the identity making the call.
Meta runs two checks, not one
Layer 1 — the permission
Does your app hold the scope, at the right access level, approved through App Review? This is the layer everyone knows and the layer every guide covers.
Layer 2 — the asset access
Does the user or system user behind this specific token have access to this specific Page, ad account, WhatsApp Business Account or Instagram account? Meta checks this independently, and it fails independently.
Meta states the mechanism plainly in its access token documentation:
The WhatsApp access token guide restates the same rule and names the error:
The error codes that mean asset, not permission
API Permission
Meta’s error-handling reference describes this range as “Permission is either not granted or has been removed.” For system-user tokens, Meta documents this same code as the response when the identity lacks access to the queried resource.
Unsupported post request
The Marketing API reference is explicit: it “may occur if your access token is not added as a system user with appropriate permissions to the ad account that owns a Custom Audience.”
Invalid Session
“User associated with the Page access token does not have an appropriate role on the Page.” The token is real. The role behind it is not sufficient.
API Permission Denied
“Permission is either not granted or has been removed.” Meta adds an eligibility dimension here too: if you are not eligible to access the endpoints, you receive this code.
API Method
“Capability or permissions issue. Make sure your app has the necessary capability or permissions to make this call.”
Invalid task combination
“This Task Combination Is Not Supported.” Assigning access with a task set Meta does not accept fails at assignment time, not at call time.
Underneath permissions sit tasks
For Pages, Meta checks a task before it checks anything else:
Meta also documents that “Page access tokens are unique to each Page, admin, and app combination” and that “if a person is given Admin access to a Page in the UI, that person is able to perform all tasks on that Page.” Individual products then name the task they need — the Messenger conversations documentation requires “a Page access token requested from a person who can perform the MESSAGING or MODERATE task on the Page,” and the Pages API getting-started page lists as a prerequisite “a Facebook Page, this can be an unpublished or published Page on which you can perform the CREATE_CONTENT task.”
Instagram professional accounts add a second namespace on top. Meta’s Instagram Platform overview states that “your app users must be able to perform tasks on the Facebook Page linked to their Instagram professional account so that they can grant your app permissions related to those tasks,” and maps them directly — PROFILE_PLUS_CREATE_CONTENT to instagram_content_publish, PROFILE_PLUS_MESSAGING to instagram_manage_messages, PROFILE_PLUS_ANALYZE to instagram_manage_insights, and so on. If the task is not there, the permission cannot be granted at all — no matter what App Review approved.
System users: the difference that breaks production
Server-to-server integrations run on system users, and this is where the asset layer bites hardest. Meta draws a hard line between two types:
Admin system users
“By default, admin system users have full access to all WhatsApp Business Accounts (WABAs) and their assets owned by or shared with you or your business portfolio.” Useful, Meta notes, when an app needs access to all of a portfolio’s assets “without having to manually grant business asset access to each asset whenever it is created, or shared.”
Employee system users
“Employee system users must be granted access to individual assets that are owned by, or shared with, your business portfolio.” Meta specifies that you must then grant Partial or Full business asset access to each asset the system user needs. Miss one asset and only that asset fails — which is exactly why the bug looks intermittent.
The app itself is an asset
Meta’s own setup instructions include assigning the app to the system user and granting Manage app permission. The app is not automatically visible to the identity that is supposed to call on its behalf.
Everything must live in the same portfolio
“Both system user and app should belong to a same Business Manager,” and “the system user and the owner of the access token used during this token generation API call must belong to the same Business Manager.” Meta adds that “apps can only target businesses (or child businesses of those businesses) that have claimed them.”
There is no UI login path
“Since a system user represents server calls, it does not have Facebook login and cannot install an app or go through the standard Facebook oAuth flow to generate a token. You need to do this via API calls.” Every fix here is an API-level fix, which is why it does not show up in the usual click-through troubleshooting.
There is also a timing trap that produces false negatives during debugging. Meta warns that “granting the permissions may take a few minutes, so reload the page if your app doesn’t appear as an assigned asset.” Teams assign an asset, immediately re-run the call, see the same error, and conclude the assignment was not the problem.
Where this quietly kills an App Review submission
The asset layer does not just break production. It blocks the submission itself, and it does so without any message that says so.
The greyed-out button
Meta’s submission guide: “the Request advanced access button will remain grayed out until a successful API has been logged in our system. A successful call must be made within 30 days of submitting for App Review. You are required to make at least 1 successful API call using each permission for which you are requesting advanced access.” An asset-access failure means no successful call — so the button never enables, and nothing tells you why.
The two-day log delay
“The API call data will be logged within 2 days of your successful API call.” So even after the real fix lands, the console does not update instantly. Teams that do not know this revert a correct change.
Premature Live mode
“Apps in Live mode can only request approved permissions from app users... This restriction applies to everyone, even users who have a role on the app itself, so switching to Live mode prematurely may make your app unusable for users who have a role on your app.” See our breakdown of development mode versus live mode.
Reviewers use their own accounts
“We will test your app using our own test accounts. Do not include your personal Meta Technologies app account’s credentials.” And: “Make sure we can access your app or website.” Anything that only works because of your own asset access will not work for them. Our post on test users and app roles covers the adjacent failure.
And above all of it: Advanced Access needs a verified business
Meta’s access levels documentation is unambiguous: “Advanced Access now requires Business Verification — As of February 1, 2023 apps requesting advanced access for permissions may have to be connected to a verified business.” It continues: “Permissions with Advanced Access can be requested from any app user... However, Business Verification is required to get Advanced Access.”
Standard Access, by contrast, “can only be requested from app users who have a role on the requesting app.” That single sentence explains the most common report we see: it works for the developer, it works for the founder, it fails for every real customer. The app never left Standard Access, and the business behind it was never verified. Meta’s 2023 announcement was explicit about the consequence — “Apps not linked to a verified business or to a business that is pending verification at that time will have their access revoked for advanced permissions.”
Advanced Access is also not a one-time gate. Meta requires apps holding it to “complete Data Use Checkup, which is an annual process to certify that the app accesses Facebook APIs, products, and data in compliance with our Platform Terms and Developer Policies.”
Why this one is hard to unpick alone
- The error text names permissions, so every instinct sends you back to a layer that is already correct.
- The failure is per-asset, so it looks random — three client accounts work, the fourth does not.
- The propagation delay and the two-day logging window both produce false negatives, so correct fixes get reverted.
- System user work has no UI shortcut — it is API-level configuration on a live business portfolio, where a wrong task assignment affects real ad accounts and real messaging.
- The App Review consequence is silent. Nothing in the console says “your asset is not assigned.” You just cannot submit.
- Portfolio ownership, app claiming, business verification and access level are four interlocking states, and diagnosing which one is wrong requires reading the actual API responses, not the settings screens.
This is the layer we map before a submission goes anywhere near Meta — asset ownership, task assignments, system user access levels, app claiming, and the access level each requested permission actually needs. It is unglamorous work and it is where a large share of stalled Meta integrations turn out to be stuck. If your submission button is greyed out or your calls fail for clients but not for you, that is the diagnostic we run as part of our Meta App Review and API approval support.