Hey guys, today in this post we are going to learn about Example with a Named Credential and custom metadata setup of Rest API POST + GET + PUT + PATCH, and DELETE in Salesforce | Named Credentials POST + GET REST API integration example to a real-world production-level setup using Named Credentials and Custom Metadata Types in Salesforce.
This is exactly how professional Salesforce developers handle secure API integrations — by removing all hardcoded URLs, headers, and credentials from Apex.
🌐 Real-World Goal
We’ll refactor your previous ContactAPICalloutService class to:
- Store API URLs securely in Named Credentials.
- Store configuration values (like API endpoints or page numbers) in Custom Metadata Type (CMDT)
- Keep Apex clean, maintainable, and reusable
🏗 Step 1. Create a Named Credential
🔹 Path:
Setup → Named Credentials → New Named Credential
| Field | Value |
|---|---|
| Label | ReqRes API |
| Name | ReqRes_API |
| URL | https://reqres.in |
| Identity Type | Anonymous |
| Authentication Protocol | No Authentication |
| Generate Authorization Header | Unchecked |
✅ Save
This means you can now use:
|
🎁 Up to 99% Off Courses (Coupon)
💥 Use Promo Code: STANDARDOFFER💥 🚀 Get Free Salesforce Course Access: www.thevijaykumar.w3web.net |
callout:ReqRes_API
in Apex safely — without hardcoding the domain.
🧱 Step 2. Create a Custom Metadata Type
CMDT Name: External_API_Config__mdt
| Field Label | API Name | Type | Example Value |
|---|---|---|---|
| API Name | DeveloperName | Text | ReqRes_Config |
| POST Endpoint | Post_Endpoint__c | Text | /api/users |
| GET Endpoint | Get_Endpoint__c | Text | /api/users?page=1 |
| Active | IsActive__c | Checkbox | TRUE |
✅ After saving the CMDT, click Manage Records → New Record, and create one record:
Label: ReqRes Config
Developer Name: ReqRes_Config
Post Endpoint: /api/users
Get Endpoint: /api/users?page=1
Is Active: ✅ Checked
⚙️ Step 3. Updated Apex Class Using Named Credential + CMDT
|
|
public class MyRestApiNamedCredentialCtrl {private static External_API_Config__mdt getActiveConfig(){
List<External_API_Config__mdt> getActiveConfig = [SELECT Post_Endpoint__c, Get_Endpoint__c, API_Key__c, Secret_Key__c FROM External_API_Config__mdt WHERE IsActive__c = TRUE ];
RETURN getActiveConfig[0];
}// ========== POST CALLOUT ==========
//@future(callout=TRUE)
public static List<Contact> sendContactToExternalAPI() {
List<Contact> conObjList = NEW List<Contact>();
try {//Contact con = [SELECT Id, FirstName, LastName, Email FROM Contact WHERE Id = :contactId LIMIT 1];
External_API_Config__mdt config = getActiveConfig();
Http http = NEW Http();
HttpRequest req = NEW HttpRequest();
req.setEndpoint('callout:ReqRes_API' + config.Post_Endpoint__c);
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setHeader(config.API_Key__c, config.Secret_Key__c);
/*Map<String, Object> body = new Map<String, Object>{'first_name' => con.FirstName,'last_name' => con.LastName,'email' => con.Email};*/Map<String, Object> bodyData = NEW Map<String, Object>();
bodyData.put('fname','Vijay02');
bodyData.put('lname','Kumar');
bodyData.put('email','exampleApi@example.com');
bodyData.put('phone','666');
req.setBody(JSON.serialize(bodyData));
HttpResponse res = http.send(req);
System.debug('POST Status: ' + res.getStatusCode());
System.debug('res Data: ' + res);
IF (res.getStatusCode() == 200 || res.getStatusCode() == 201) {
Map<String, Object> resMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
string fname = (string)resMap.get('fname');
string lname = (string)resMap.get('lname');
string email = (string)resMap.get('email');
string phone = (string)resMap.get('phone');
//system.debug('resMap ' + resMap);
Contact conItem = NEW Contact();
conItem.FirstName = fname;
conItem.LastName = lname;
conItem.Email = email;
conItem.Phone=phone;
INSERT conItem;system.debug('recId' + conItem.Id);
conObjList.add(conItem);
System.debug('✅ POST Success — record inserted');
} ELSE {
System.debug('❌ POST Error: ' + res.getBody());
}} catch (Exception e) {
System.debug('⚠️ POST Exception: ' + e.getMessage());
}system.debug('conObjList' + conObjList);
RETURN conObjList;}// ========== GET CALLOUT ==========
////@future(callout=TRUE)
public static List<External_User__c> getExternalUserData() {
List<External_User__c> usersList = NEW List<External_User__c>();
try{External_API_Config__mdt config = getActiveConfig();
Http h = NEW Http();
HttpRequest req = NEW HttpRequest();
req.setEndpoint('callout:ReqRes_API' + config.Get_Endpoint__c);
req.setMethod('GET');
req.setHeader('Content-Type', 'application/json');
req.setHeader(config.API_Key__c, config.Secret_Key__c);
HttpResponse res = h.send(req);
system.debug('status ' + res.getStatusCode());
//System.debug('GET Status: ' + res.getStatusCode());
IF(res.getStatusCode() == 200 || res.getStatusCode() == 201){
Map<string, Object> resMap = (Map<string, Object>) JSON.deserializeUntyped(res.getBody());
List<Object> objList = (List<Object>) resMap.get('data');
system.debug('resMap ' + resMap);
system.debug('objList ' + objList);
FOR(Object obj: objList){
Map<string, Object> objRes = (Map<string, Object>) obj;
External_User__c USER = NEW External_User__c();
//system.debug('objRes ' + objRes);
String first_name = (String) objRes.get('first_name');
String avatar = (String) objRes.get('avatar');
String last_name = (String) objRes.get('last_name');
String email = (String) objRes.get('email');
USER.First_Name__c = first_name;
USER.Last_Name__c = last_name;
USER.Email__c = email;
USER.Avatar_URL__c = avatar;
usersList.add(USER);
}}}catch(Exception e){
System.debug('⚠️ GET Exception: ' + e.getMessage());
}system.debug('usersList' + usersList);
RETURN usersList;}// ========== PUT CALLOUT ==========
////@future(callout=TRUE)
//public static void putDataService(Id recordId){
try{External_API_Config__mdt config = getActiveConfig();
Contact con = [SELECT Id, FirstName, LastName FROM Contact WHERE Id =:recordId];
Http h = NEW Http();
HttpRequest req = NEW HttpRequest();
//req.setEndpoint('callout:ReqRes_API' + config.Post_Endpoint__c);
req.setEndpoint('https://reqres.in/api/users/');
req.setMethod('PUT');
req.setHeader('Content-Type', 'application/json');
req.setHeader(config.API_Key__c, config.Secret_Key__c);
req.setBody('{"name":"Vjy2", "email":"vjy@example.com"}');
HttpResponse res = h.send(req);
system.debug('StagusCode ' + res.getStatusCode());
IF(res.getStatusCode() == 200 || res.getStatusCode() == 201){
Map<String, Object> resMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
system.debug('resMap ' + resMap);
string name = (String) resMap.get('name');
string phone = (String) resMap.get('phone');
con.LastName = name;
con.Phone = phone;
con.Id = con.Id;
UPDATE con;}}catch(Exception e){
system.debug('Exception ' + e.getMessage());
}}// ========== PATCH CALLOUT ==========
////@future(callout=TRUE)
//public static void patchDataService(Id recordId){
try{Contact con = [SELECT Id, FirstName, LastName FROM Contact WHERE Id=:recordId];
External_API_Config__mdt config = getActiveConfig();
Http h = NEW Http();
HttpRequest req = NEW HttpRequest();
//req.setEndpoint('callout:ReqRes_API' + config.Post_Endpoint__c);
req.setEndpoint('https://reqres.in/api/users/');
req.setMethod('PATCH');
req.setHeader('Content-Type', 'application/json');
req.setHeader(config.API_Key__c, config.Secret_Key__c);
req.setBody('{"name":"Vjy_02", "email":"vjy@example.com"}');
HttpResponse res = h.send(req);
system.debug('StagusCode ' + res.getStatusCode());
IF(res.getStatusCode() == 200 || res.getStatusCode() == 201){
Map<String, Object> resMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
String lname = (String) resMap.get('name');
String email = (String) resMap.get('email');
IF(con.LastName == lname){
con.LastName = lname;
con.Email = email;
con.Id = con.Id;
UPDATE con;system.debug('Updated ' + con.Id);
}ELSE{
Contact conObj = NEW Contact();
conObj.LastName = lname;
conObj.Email = email;
INSERT conObj;system.debug('Inserted ' + conObj.Id);
}}}catch(Exception e){
system.debug('Exception ' + e.getMessage());
}}// ========== DELETE CALLOUT ==========
////@future(callout=TRUE)
//public static void deleteDataService(Id recordId){
try{Contact con = [SELECT Id, FirstName, LastName FROM Contact WHERE Id=:recordId];
External_API_Config__mdt config = getActiveConfig();
Http h = NEW Http();
HttpRequest req = NEW HttpRequest();
//req.setEndpoint('callout:ReqRes_API' + config.Post_Endpoint__c);
req.setEndpoint('https://reqres.in/api/users/');
req.setMethod('DELETE');
req.setHeader('Content-Type', 'application/json');
req.setHeader(config.API_Key__c, config.Secret_Key__c);
HttpResponse res = h.send(req);
system.debug('StagusCode ' + res.getStatusCode());
DELETE con;system.debug('Record Deleted Successfully');
}catch(Exception e){
system.debug('Exception ' + e.getMessage());
}}}
🧪 Step 4. Test in Execute Anonymous Window
🔹 For POST Callout
Contact testCon = NEW Contact(FirstName='Vijay', LastName='Kumar', Email='vijay@example.com');
INSERT testCon;MyRestApiNamedCredentialCtrl.sendContactToExternalAPI(testCon.Id);
System.debug('🚀 POST API Callout triggered using Named Credential + CMDT');
🔹 For GET Callout
ContactAPICalloutService.getExternalUserData();
System.debug('🚀 GET API Callout triggered using Named Credential + CMDT');
📊 Step 5. Debug Results
- Check Setup → Apex Jobs for async job results.
- Check your Custom Objects (External_Response__c and External_User__c) for inserted data.
- Observe System.debug logs for response details.
✅ Advantages of This Setup
| Feature | Description |
|---|---|
| 🔒 Secure | No hardcoded URLs or credentials in Apex |
| ⚙️ Configurable | Admins can change API endpoints directly from CMDT |
| 🔁 Reusable | Same class can work for multiple APIs with just new CMDT records |
| 🧰 Scalable | Easily add headers, authentication tokens, or more configs later |
Further post that would you like to learn in Salesforce
How to get metadata from rest API?
You can use the GET operation to retrieve field metadata for specified fields on a specified form as defined in the criteria. The following table lists details about this GET operation. Indicates the list of field ids for which details are required. The API returns the requested data if you provide the criteria.
What is a named credential?
A named credential specifies the URL of a callout endpoint and its required authentication parameters in one definition. Salesforce manages all authentication for Apex callouts that specify a named credential as the callout endpoint so that your code doesn't have to.
Which components can use the rest API metadata?
Once the REST API metadata is created, you can use it in the tRESTRequest component with Jobs and cREST with Routes. In the Basic settings view of the tRESTRequest component, select Repository from the Definition list.
Related Topics | You May Also Like
|
👉 Get Free Course →
📌 Salesforce Administrators 📌 Salesforce Lightning Flow Builder 📌 Salesforce Record Trigger Flow Builder |
👉 Get Free Course → |

