Forum Discussion
Query for Salesforce API connection
- 3 months ago
Hi,
Bad Request on the token endpoint almost always means Salesforce is rejecting the request itself (not a Power BI connectivity issue), so I'd look at these first:
1. Check the Connected App is actually set up for Client Credentials Flow This is the most common gotcha — just having a Client ID/Secret isn't enough. In Salesforce Setup, on your Connected App, you need "Enable Client Credentials Flow" explicitly turned on under OAuth settings, and there needs to be a "Run As" user assigned to it. If that's not configured, you'll get a Bad Request even with correct credentials.
2. Try capturing the actual error body, not just the status Right now you won't see Salesforce's actual error message because Power Query throws before you can inspect the response. Add ManualStatusHandling = {400} to your Web.Contents options so you can capture the response body:
TokenResponse = Web.Contents(SalesforceUrl & "/services/oauth2/token", [ Content = Text.ToBinary("grant_type=client_credentials&client_id=" & ClientId & "&client_secret=" & ClientSecret), Headers = [#"Content-Type"="application/x-www-form-urlencoded"], ManualStatusHandling = {400} ]), ResponseText = Text.FromBinary(TokenResponse)Then just output ResponseText on its own to see what Salesforce is actually telling you (usually something like invalid_client_id or unsupported_grant_type which narrows it down immediately).
3. Double check there's no IP restriction issue If the Connected App or your Salesforce org has IP allowlisting/login IP ranges enforced, requests coming from Power BI's service (if this is going through the Power BI service rather than just Desktop) can get blocked at a level that also shows up as a generic Bad Request.
4. Confirm you're not mixing up Consumer Key/Secret with something else Sounds basic, but worth confirming ClientId/ClientSecret in your code are the actual Consumer Key and Consumer Secret from the Connected App's "Manage Consumer Details" page, not the connected app's Salesforce record Id or anything else.
Once you get the actual error text back from step 2, that'll tell you exactly which of these it is rather than guessing. Post that response back if you're still stuck and it'll be much easier to pin down.
Bad Request from the token endpoint almost always hides a more specific error that Web.Contents swallows by default. First, add ManualStatusHandling = {400} to your Web.Contents options and parse the response body - that will show Salesforce's actual error code (e.g. invalid_client, unsupported_grant_type). Two common culprits: 1) The request body isn't URL-encoded - if your Client Secret has characters like +, /, or =, plain string concatenation will corrupt it. Build the body with Uri.BuildQueryString([grant_type="client_credentials", client_id=ClientId, client_secret=ClientSecret]) instead of manual string concatenation. 2) Client Credentials Flow needs to be explicitly enabled on your Connected App's OAuth policies with a designated "Run As" user - if that's not configured, Salesforce rejects the grant before it even checks your credentials. Worth confirming both of these with your Salesforce admin.