D360 Notes: How to Call Salesforce API from Apex
A call to your own Salesforce org might not be so simple…
Calling Salesforce’s own API from Apex sounds simple. You are already inside the platform, so how hard could it be?
Turns out, there is a fair amount of configuration between that idea and the first request.
An External Client App, an External Credential, a Permission Set, and a Named Credential.
All before Apex sends anything.
At that point, Apex starts to feel like the easy part. The question is why you need all these pieces and which one does what.
My goal was to schedule a D360 Data Graph refresh. Before calling the Data 360 API, I needed a working API connection. This article covers that first step: setting up authentication and making a simple test call.
We’ll use OAuth 2.0 Client Credentials. It suits this kind of background automation because the connection uses a fixed integration user and doesn’t require anyone to log in through a browser.
The Four Config Pieces
Each piece has a specific job:
- External Client App: registers the app and sets which Salesforce user its requests will run as.
- External Credential: tells Salesforce how to get an access token using the app’s client ID and secret.
- Permission Set: lets users send requests through this connection.
- Named Credential: saves the API address and links it to the External Credential.
Salesforce keeps these settings separate so they can be reused. That also means several setup screens to visit.
Putting the Connection Together
We’ll configure the app first, then connect it to the credentials that Apex is going to use.
Choose an active Salesforce user for the automation. This integration user needs API access. For the Data Graph refresh later, it will also need the relevant Data 360 permissions and data space access.
1. Register the External Client App
Go to Setup → External Client App Manager → New External Client App.
Enter an app name and contact email, then enable OAuth. Select Enable Client Credentials Flow.
In this example, I selected these scopes:
- Manage user data via APIs
api: allows access to Salesforce APIs. - Access all Data Cloud API resources
cdp_api: allows access to Data Cloud API resources.
The form also requires a Callback URL. Enter:
https://localhost/callbackThis flow doesn’t use the callback URL. It is a placeholder to let you save the app.
Here’s the setup screen:
After creating the app, open Policies → Edit. Under OAuth Flows and External Client App Enhancements, make sure Client Credentials Flow is enabled and select your integration user in Run As.
This user’s permissions determine what the API requests can access.
Save, then open Settings → OAuth Settings → Consumer Key and Secret.
Copy these values somewhere secure. You’ll need them in the next step.
2. Create the External Credential
Go to Setup → Named Credentials → External Credentials → New.
Get Antonin Puskarcik’s stories in your inbox
Join Medium for free to get updates from this writer.
Use the following settings:
Copy your actual URL from Setup → My Domain. For a sandbox, the token address looks like this:
https://<your_sf_domain>.sandbox.my.salesforce.com/services/oauth2/tokenThis is where Salesforce sends the client ID and secret to get a token.
Save, then open Principals → New. This is where you enter the app’s credentials:
Save. There is no browser login step. Salesforce will use these credentials to request a token when needed.
3. Grant Permission to Use the Connection
Go to Setup → Permission Sets. Create a permission set such as Use_SF_Self_API, or use an existing one:
Open External Credential Principal Access → Edit and add the principal created in the previous step:
Save, then open Manage Assignments and assign the permission set to yourself, because you’ll run the Apex test script.
This lets you use the connection. The user selected in the App’s Run As field determines what data the request can access.
Also check Object Settings → User External Credentials. For this OAuth Named Principal flow, Salesforce requires Modify All Records for that object, which your profile may already provide.
4. Create the Named Credential
Go to Setup → Named Credentials → Named Credentials → New.
Use the following configuration:
Use only the base URL here. For a sandbox:
https://<your_sf_domain>.sandbox.my.salesforce.comKeep /services/oauth2/token in the External Credential. The Named Credential holds the address for the API requests.
Save. You can now use SF_Self_API in Apex.
Finally, we are ready!
Testing if It Works
Now let’s try running a simple GET request.
Open Developer Console from the gear icon. Then go to Debug → Open Execute Anonymous Window.
This window runs Apex directly, so you don’t need to create a class for the test. Paste:
HttpRequest request = new HttpRequest();
request.setEndpoint(
'callout:SF_Self_API/services/data/v66.0/limits'
);
request.setMethod('GET');
HttpResponse response = new Http().send(request);
System.debug('Status: ' + response.getStatusCode());
System.debug('Response: ' + response.getBody());Select Open Log, then click Execute. In the log, select Debug Only.
Look for Status: 200 and a JSON response containing entries such as DailyApiRequests. That confirms the request worked.
The limits section at the bottom of an Apex log is something else. It shows the resources used by the Apex code. It appears even when the API request fails. I managed to mistake that for success during my first attempt.
This is only a connection test. We haven’t refreshed a Data Graph yet.
So What Did We Actually Configure?
It took me longer to understand this setup than to write the Apex.
When the code uses SF_Self_API, Salesforce looks up the API address. It uses the linked External Credential to get a token with the app’s client ID and secret and adds that token to the request.
The user selected in Run As determines what the request can access.
That is what all those screens were preparing.
Along the way, an extra dot in my configuration stopped the token request, and a missing .sandbox in the API address stopped the next call. Neither error message made the issue obvious.
But now the connection works. Next comes refreshing a Data Graph on a schedule.
The other authentication options, and when to use them, deserve an article of their own.
If you work with Salesforce Data Cloud, CDPs, segmentation, or marketing data models, I’d be happy to connect and exchange thoughts.









