Microsoft Advertising API - 401 Unauthorized when calling Customer Management API (e.g., GetAccounts) despite successful OAuth consent and valid access token
We're building a SaaS application with Microsoft Advertising (Bing Ads) integration. Users authenticate via OAuth2 using the Microsoft Identity Platform.
Authentication flow:
- Authorization endpoint: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
- Scopes requested: openid offline_access https://ads.microsoft.com/msads.manage
- Token endpoint: https://login.microsoftonline.com/common/oauth2/v2.0/token
- We successfully receive an authorization code, exchange it for access_token + refresh_token, and refresh tokens work fine (tokens are valid and not expired).
The user sees the consent screen, grants permission to all requested scopes (including msads.manage), and everything looks good on the OAuth side.
However, when we use the access_token to call the Customer Management Service (SOAP) or Reporting/Campaign Management endpoints — for example, to fetch the user's accounts list via GetAccountsInfo or similar — we immediately get a 401 Unauthorized error.
Error example (from the response headers/body):
text
Illuminate\Http\Client\Response {#1847 // app/Helpers/BingHelper.php:320
Or similar JSON/plain text 401 responses depending on the endpoint.
We've confirmed:
- Developer token is correctly set and approved.
- AuthenticationToken header is the OAuth access_token.
- CustomerId/AccountId headers are attempted (though not yet known since we can't list accounts).
- No MFA issues apparent during consent.
- Token decode (jwt.io) shows the correct scopes and audience.
This happens even though the user has an active Microsoft Advertising account and has granted consent.We're building a SaaS application with Microsoft Advertising (Bing Ads) integration. Users authenticate via OAuth2 using the Microsoft Identity Platform.
Authentication flow:
- Authorization endpoint: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
- Scopes requested: openid offline_access https://ads.microsoft.com/msads.manage
- Token endpoint: https://login.microsoftonline.com/common/oauth2/v2.0/token
- We successfully receive an authorization code, exchange it for access_token + refresh_token, and refresh tokens work fine (tokens are valid and not expired).
The user sees the consent screen, grants permission to all requested scopes (including msads.manage), and everything looks good on the OAuth side.
However, when we use the access_token to call the Customer Management Service (SOAP) or Reporting/Campaign Management endpoints — for example, to fetch the user's accounts list via GetAccountsInfo or similar — we immediately get a 401 Unauthorized error.
Error example (from the response headers/body):
text
Illuminate\Http\Client\Response {#1847 // app/Helpers/BingHelper.php:320
#response: GuzzleHttp\Psr7\Response {#342
reasonPhrase: "Unauthorized"
statusCode: 401
headers: array:6 [ … ]
body: <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
...
</s:Fault>
</s:Body>
</s:Envelope>
}
}
Or similar JSON/plain text 401 responses depending on the endpoint.
We've confirmed:
- Developer token is correctly set and approved.
- AuthenticationToken header is the OAuth access_token.
- CustomerId/AccountId headers are attempted (though not yet known since we can't list accounts).
- No MFA issues apparent during consent.
- Token decode (jwt.io) shows the correct scopes and audience.
This happens even though the user has an active Microsoft Advertising account and has granted consent.
We are also attaching the code that we are using it so please guide us how we can solve this issue.bing_account.txt