Can the Metadata API be invoked from Apex?

Can the Metadata API be invoked from Apex?

On June 7, 2025, Posted by , In Salesforce Technical Questions, With Comments Off on Can the Metadata API be invoked from Apex?
Can the Metadata API be invoked from Apex

Question:

Is it possible to invoke the Salesforce Metadata API from within Apex? Many developers believe this is not allowed, but some have suggested it might be possible. While it’s generally accepted that you can’t call Salesforce web services from within Salesforce itself, others claim to have made it work. Has anyone successfully used the Metadata API from within Apex, and if so, how?

Answer:

Yes, it is indeed possible to invoke the Metadata API from within Apex, although it’s a bit tricky. The key challenge is that Salesforce does not allow direct calls to web services like the Metadata API from within Apex. However, there are workarounds, such as using the WSDL2Apex tool to generate the necessary Apex code for interacting with the Metadata API.

Elevate your career with CRS Info Solutions’ expert-led Salesforce training in Hyderabad, providing hands-on experience and comprehensive knowledge to master the Salesforce ecosystem.

The process generally involves generating the WSDL from Salesforce and then using the WSDL2Apex tool to generate the Apex classes needed to call the API. Once you have the generated classes, you can use them to create metadata records, such as custom objects, through asynchronous operations.

For example, here’s a basic snippet of how you can create a custom object using the Metadata API from Apex:

MetadataService.MetadataPort service = createService();
MetadataService.CustomObject customObject = new MetadataService.CustomObject();
customObject.fullName = 'Test__c';
customObject.label = 'Test';
customObject.pluralLabel = 'Tests';
customObject.nameField = new MetadataService.CustomField();
customObject.nameField.type_x = 'Text';
customObject.nameField.label = 'Test Record';
customObject.deploymentStatus = 'Deployed';
customObject.sharingModel = 'ReadWrite';

MetadataService.AsyncResult[] results = 
    service.create(new List<MetadataService.Metadata> { customObject });

Explanation:

The code creates a custom object (Test__c) using the Metadata API by defining its properties, such as label, name field, and sharing model. It then asynchronously deploys the custom object through the create() method of the MetadataPort service, returning the operation’s results.

The key thing to note here is that most of the Metadata API methods, such as create(), return an AsyncResult. This means you’ll need to implement some sort of polling solution to check the status of the operation.

Additionally, there’s an option to use the Metadata REST API, which is in pilot and may provide a more modern solution. However, as of now, it’s still in development and not yet generally available.

Other examples

1. Using Named Credentials and an External Service

Steps:

  • Create a Named Credential in Salesforce and configure authentication.
  • Set up an external service (AWS, Heroku, or another cloud platform) to process Metadata API requests.
  • Implement an API endpoint in the external service that accepts requests from Salesforce.
  • Ensure the external service handles OAuth authentication with Salesforce.
  • Make an Apex HTTP callout using the Named Credential to invoke the external API.
  • Process the response from the Metadata API and return it to Salesforce.

Apex Code

public class MetadataAPICaller {
    public static void callMetadataAPI() {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:MyNamedCredential/metadataApiEndpoint'); // Named Credential
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json');
        req.setBody('{"someKey": "someValue"}');  // Modify request body as needed

        Http http = new Http();
        HttpResponse res = http.send(req);
        
        System.debug('Response: ' + res.getBody());
    }
}

This approach to invoking the Metadata API from Apex is using Named Credentials and an external service. Named Credentials allow secure storage of authentication details and simplify API callouts without manually handling OAuth tokens. In this method, Salesforce makes an HTTP callout to an external service, which then interacts with the Metadata API.

The external service, which can be hosted on platforms like AWS Lambda or Heroku, processes the request and sends back the response to Salesforce. This approach is secure and aligns with Salesforce best practices, but it requires setting up and maintaining an external service to handle Metadata API interactions.

2. Using OAuth Authentication for Direct Callout

Steps:

  1. Create a Salesforce Connected App to obtain OAuth credentials.
  2. Write an Apex method to obtain an OAuth access token using a username-password flow or client credentials.
  3. Store the access token securely in a custom setting or custom metadata.
  4. Use the access token in an HTTP callout from Apex to the Metadata API.
  5. Send a request to create, update, or retrieve metadata components.Process and handle the API response in Apex.

Apex Code

public class MetadataAPIService {
    private static final String AUTH_URL = 'https://login.salesforce.com/services/oauth2/token';
    private static final String CLIENT_ID = 'your_client_id';
    private static final String CLIENT_SECRET = 'your_client_secret';
    private static final String USERNAME = 'your_username';
    private static final String PASSWORD = 'your_password';

    public static String getAccessToken() {
        HttpRequest req = new HttpRequest();
        req.setEndpoint(AUTH_URL);
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.setBody('grant_type=password' +
                    '&client_id=' + CLIENT_ID +
                    '&client_secret=' + CLIENT_SECRET +
                    '&username=' + USERNAME +
                    '&password=' + PASSWORD);
        
        Http http = new Http();
        HttpResponse res = http.send(req);
        
        if (res.getStatusCode() == 200) {
            Map<String, Object> responseMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
            return (String) responseMap.get('access_token');
        } else {
            throw new CalloutException('Failed to authenticate: ' + res.getBody());
        }
    }

    public static void callMetadataAPI() {
        String accessToken = getAccessToken();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://yourInstance.salesforce.com/services/Soap/m/57.0'); // Update API version if needed
        req.setMethod('POST');
        req.setHeader('Authorization', 'Bearer ' + accessToken);
        req.setHeader('Content-Type', 'application/xml');
        req.setBody('<your-metadata-api-request-xml-here>');

        Http http = new Http();
        HttpResponse res = http.send(req);
        
        System.debug('Response: ' + res.getBody());
    }
}

This approach involves using OAuth authentication to make a direct callout from Apex. Since Salesforce does not allow direct API calls to its own services, developers must first obtain an OAuth access token from Salesforce’s authentication endpoint. The access token is then used in an HTTP request from Apex to the Metadata API.

This method enables direct interaction with metadata components, such as creating or updating metadata records. However, Salesforce’s built-in security restrictions make it challenging to call its own services directly. To bypass these restrictions, developers often use an external OAuth flow or middleware service to facilitate the API call.

3. Using the Tooling API Instead of Metadata API

Steps:

  1. Create a Salesforce Connected App for OAuth authentication.
  2. Write an Apex method to retrieve an access token.
  3. Use Apex HTTP callouts to query metadata through the Tooling API.
  4. Retrieve metadata details such as Apex classes, fields, and objects.Process the response and update records as needed in Salesforce.
  5. Handle error responses and API limits in Apex.

Apex Code

public class ToolingAPIService {
    public static void queryApexClasses() {
        String accessToken = MetadataAPIService.getAccessToken(); // Reuse OAuth method
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://yourInstance.salesforce.com/services/data/v57.0/tooling/query/?q=SELECT+Id,Name+FROM+ApexClass');
        req.setMethod('GET');
        req.setHeader('Authorization', 'Bearer ' + accessToken);
        req.setHeader('Content-Type', 'application/json');

        Http http = new Http();
        HttpResponse res = http.send(req);
        
        System.debug('Response: ' + res.getBody());
    }
}

This approach leverages the Tooling API instead of the Metadata API. The Tooling API allows developers to retrieve and modify certain metadata components, such as Apex classes, custom fields, and objects. This method is easier to implement because Apex can directly make HTTP callouts to the Tooling API without requiring an external service.

The process involves obtaining an OAuth access token and making an API request to query metadata details. While the Tooling API is useful for retrieving metadata, it has limitations, as it does not support full metadata operations like creating new objects or fields. This makes it a suitable alternative only for specific use cases.

4. Using Salesforce Functions

Steps:

  1. Set up Salesforce Functions and deploy a function using Node.js or Java.
  2. Write the function to make an external API call to the Metadata API.Configure authentication within the function using OAuth credentials.
  3. Call the Salesforce Function from an Apex class using an HTTP request.Process metadata updates within the function and return the response.
  4. Handle API errors and retry logic within the function.

Node.js Salesforce Function

// Node.js function to call Metadata API
const { Client } = require('@salesforce/functions');
const axios = require('axios');

module.exports = async function (event, context, logger) {
    let accessToken = process.env.SF_ACCESS_TOKEN;
    let instanceUrl = process.env.SF_INSTANCE_URL;

    let response = await axios.post(`${instanceUrl}/services/Soap/m/57.0`, '<xml-payload>', {
        headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Content-Type': 'application/xml'
        }
    });

    return response.data;
};

Apex Code to Call Salesforce Function

public class CallSalesforceFunction {
    public static void invokeFunction() {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://functions.salesforce.com/my-function-endpoint');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json');
        req.setBody('{"request": "metadata-update"}');

        Http http = new Http();
        HttpResponse res = http.send(req);

        System.debug('Function Response: ' + res.getBody());
    }
}

This approach involves using Salesforce Functions to invoke the Metadata API. Salesforce Functions allow developers to run external code (such as Node.js or Java) in a cloud environment that integrates with Salesforce. In this method, an Apex class calls a Salesforce Function, which then interacts with the Metadata API.

The function processes the metadata request externally and sends back the response. This approach is highly scalable and avoids the self-callout limitations of Apex, making it an effective solution for complex metadata operations. However, it requires setting up Salesforce Functions, which may involve additional licensing and infrastructure considerations.

Which Method Should You Use?

ApproachProsCons
Named Credentials with External ServiceSecure, easier authenticationRequires external service setup
OAuth Callout to Metadata APIDirect interaction with Metadata APINeeds OAuth setup, Salesforce callout limits
Tooling API CalloutCan retrieve some metadataLimited in scope (no full metadata modifications)
Salesforce FunctionsBest for scalability, handles metadata updatesRequires Salesforce Functions setup

Salesforce Training in Hyderabad: Your Gateway to Success

Unlock your potential with our in-depth Salesforce training in Hyderabad . We offer comprehensive courses covering Admin, Developer, and AI tracks to ensure you gain the skills needed to thrive in the tech industry. With structured modules, hands-on projects, and expert-led sessions, you’ll be ready for certification and interviews.

Join our free demo class today and get a glimpse of our practical, industry-oriented training. Our experienced instructors provide personalized guidance, Salesforce Course helping you grasp complex concepts easily. Whether you’re a beginner or looking to advance your career, our program prepares you for real-world challenges and career growth.

Join our free demo class today and take the first step toward a rewarding future! Enroll now for a free demo!!!

Comments are closed.