
Hey Learners! Creating records in Salesforce for Customer Community Plus users is now more accessible and efficient with REST API capabilities. You can streamline authentication by leveraging a session ID as a token, making API calls secure and straightforward. This method allows seamless integration with custom apps and external systems, enabling developers to focus on functionality without being bogged down by complex security protocols.
Whether you're automating workflows or enhancing user experiences, using a session ID for authentication reduces complexity while maintaining Salesforce’s robust security standards. Discover how this approach can transform your record creation process and elevate your customer community integrations with minimal effort!
Why REST API and Session ID?
The Salesforce REST API allows for smooth interaction between external systems and Salesforce data. The session ID is an authentication token for Customer Community Plus users, eliminating the need for external authentication mechanisms like OAuth flows. This approach benefits Experience Cloud sites, where users frequently interact with custom objects.
Building the Framework
To create an Application record, we will use a combination of Salesforce REST API calls, Experience Cloud settings, and HTML Lightning Web Components (LWC) for user inputs. Below is a simple LWC template used to capture and submit record details:

This component simplifies user interaction by allowing inputs to be mapped directly to the Application custom object. It uses the lightning-record-edit-form tag to handle the record creation process and provides feedback for success or error scenarios.
Common Error:
When creating an Application record as a Customer Community Plus user, a common error occurs:
"Error creating record: You don’t have access to this record. Ask your administrator for help or to request access."

Quick Note: Setting Up a Customer Community Plus User
Before diving into the record creation process, Please ensure Digital Experience is enabled, Allow using standard external profiles for self-registration, user creation, and login, also you’ve set up your Experience Cloud user properly and the user must have a Role assigned. If you’re unfamiliar with creating users for Experience Cloud, check out my previous blog here for a detailed guide. In that blog, I walk you through the entire process, please assign the Customer Community Plus User profile to the user, which is essential for the functionality we’re discussing today.
Once your user is set up with the correct profile, you’re ready to proceed with creating records using the REST API. Let’s dive in!
Step 1: Create an LWC Component
Start by creating a Lightning Web Component (LWC) named ApplicationForm. This will serve as the UI for capturing user input.
Run the following Salesforce CLI command to generate the component:
sfdx force:lightning:component:create --type lwc --componentname applicationForm
This command creates the necessary files: applicationForm.html, applicationForm.js, and applicationForm.css.
Step 2 - Set Up the Component HTML
In applicationForm.html, set up a simple user interface that will display the Application Form
<template>
<lightning-card>
<div slot="title">
<h3>
<lightning-icon icon-name={labels.CONTACT_ICON} size="small"></lightning-icon> {labels.APPLICATION_FORM}
</h3>
</div>
<div class="slds-grid slds-wrap">
<div class="slds-p-horizontal--small slds-col slds-size_6-of-12 slds-m-bottom--medium">
<div class="slds-form-element data-input">
<lightning-input label={labels.APPLICATION_NAME} value={name} onchange={nameChange}>
</lightning-input>
</div>
</div>
<div class="slds-p-horizontal--small slds-col slds-size_6-of-12 slds-m-bottom--medium ">
<div class="slds-form-element checkbox-input">
<lightning-input type="checkbox" label={labels.APPLICATION_SELECTION} checked={isChecked} onchange={selectionChange}>
</lightning-input>
</div>
</div>
</div>
<div class="button">
<lightning-button type="submit" label={labels.BUTTON_LABEL} onclick={handleSubmit}></lightning-button>
</div>
</lightning-card>
</template>
Step 3 - Set Up the Component JS
import {LightningElement, track} from 'lwc';
import {ShowToastEvent} from 'lightning/platformShowToastEvent';
import CalloutExample from '@salesforce/apex/ApplicationFormContoller.calloutExample';
import APPLICATION from '@salesforce/schema/Application__c';
import CONTACT_ICON from '@salesforce/label/c.CONTACT_ICON';
import APPLICATION_NAME from '@salesforce/label/c.APPLICATION_NAME';
import APPLICATION_FORM from '@salesforce/label/c.APPLICATION_FORM';
import APPLICATION_SELECTION from '@salesforce/label/c.APPLICATION_SELECTION';
import BUTTON_LABEL from '@salesforce/label/c.CREATE_APPLICATION_BUTTON_LABEL';
import SUCCESS_TOAST_MESSAGE from '@salesforce/label/c.APPLICATION_CREATION_TOAST_MESSAGE';
export default class ApplicationForm extends LightningElement {
@track name = '';
@track isChecked = false;
labels = {
CONTACT_ICON,
APPLICATION_NAME,
APPLICATION_FORM,
APPLICATION_SELECTION,
BUTTON_LABEL,
SUCCESS_TOAST_MESSAGE
}
selectionChange(event) {
this.isChecked = event.target.checked;
}
nameChange(event) {
this.name = event.target.value;
}
handleSubmit() {
CalloutExample({ objectApiName: APPLICATION.objectApiName, name: this.name, isSelected: this.isChecked })
.then(result => {
this.showToast('Success', this.name + this.labels.SUCCESS_TOAST_MESSAGE, 'success');
})
.catch(error => {
this.showToast('Error', error.body.message, 'error');
});
}
showToast(title, message, variant) {
const event = new ShowToastEvent({
title: title,
message: message,
variant: variant,
});
this.dispatchEvent(event);
}
}
Step 4 - Set Up the Component CSS
.button {
margin-left: 0.9rem;
}
.checkbox-input {
margin-top: 2rem;
float: right;
margin-right: 3rem;
}
Step 5 - Set Up the Apex Class (ApplicationFormController) :
public with sharing class ApplicationFormContoller {
/**
* Creates a record in Salesforce using the REST API.
*
* @param sObjectName The API name of the Application to create.
* @param recordData A map of field names and values for the new Application.
* @return The ID of the newly Application record.
* @throws CalloutException If there is an issue with the HTTP request.
*/
public static String createRecord(String sObjectName, Map<String, Object> recordData) {
String baseUrl = System.URL.getOrgDomainUrl().toExternalForm();
String restEndpoint = baseUrl + '/services/data/v57.0/sobjects/' + sObjectName;
String requestBody = JSON.serialize(recordData);
HttpRequest req = new HttpRequest();
req.setEndpoint(restEndpoint);
req.setMethod('POST');
req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
req.setHeader('Content-Type', 'application/json');
req.setBody(requestBody);
Http http = new Http();
HttpResponse res = http.send(req);
if (res.getStatusCode() == 201) {
return (String) res.getBody();
} else {
throw new CalloutException(res.getStatusCode() + ' - ' + res.getBody());
}
}
@AuraEnabled
public static String calloutExample(String objectApiName, String name, Boolean isSelected) {
Map<String, Object> recordFields = new Map<String, Object>{
System.Label.APPLICATION_NAME_FIELD => name,
System.Label.APPLICATION_SELECTION_FIELD => isSelected
};
return createRecord(objectApiName, recordFields);
}
}
Optional Step 6 - Set Up the Apex test Class (ApplicationFormControllerTest) :
***********************************************************************/
@IsTest
public class ApplicationFormControllerTest {
@TestSetup
static void setupTestData() {
Profile customerCommunityPlusProfile = [
SELECT
Id
FROM
Profile
WHERE
Name = 'Customer Community Plus User'
];
Account testAccount = new Account(Name = 'Test Account');
insert testAccount;
Contact testUserContact = new Contact(LastName = 'Test Contact', AccountId = testAccount.Id);
insert testUserContact;
Test.startTest();
User testUser = new User(
Alias = 'testuser',
Email = 'testuser@example.com',
EmailEncodingKey = 'UTF-8',
LastName = 'Test',
LanguageLocaleKey = 'en_US',
LocaleSidKey = 'en_US',
ContactId = testUserContact.Id,
ProfileId = customerCommunityPlusProfile.Id,
TimeZoneSidKey = 'America/Los_Angeles',
UserName = 'testuser885533@example.com'
);
insert testUser;
Test.stopTest();
}
@IsTest
static void testCreateApplicationSuccess() {
Map<String, Object> applicationData = new Map<String, Object>{
'Name' => 'Test Application',
'Selected__c' => true
};
Test.startTest();
HttpCalloutMock mock = new ApplicationFormControllerMock(201, '{"success":true,"errors":[]}');
Test.setMock(HttpCalloutMock.class, mock);
String response = ApplicationFormContoller.calloutExample(
'Application__c',
(String) applicationData.get('Name'),
(Boolean) applicationData.get('Selected__c')
);
Test.stopTest();
System.assertEquals(
'{"success":true,"errors":[]}',
response,
'Callout response success message must be true'
);
}
@IsTest
static void testCreateApplicationFailure() {
Map<String, Object> applicationData = new Map<String, Object>{
'Name' => 'Test Application',
'Is_Selected__c' => false
};
Test.startTest();
HttpCalloutMock mock = new ApplicationFormControllerMock(400, '{"message":"Bad Request"}');
Test.setMock(HttpCalloutMock.class, mock);
try {
String response = ApplicationFormContoller.calloutExample(
'Application__c',
(String) applicationData.get('Name'),
(Boolean) applicationData.get('Is_Selected__c')
);
System.assert(false, 'Exception was expected but not thrown.');
} catch (CalloutException ex) {
System.assertEquals(
'400 - {"message":"Bad Request"}',
ex.getMessage(),
'Exception message should match.'
);
}
Test.stopTest();
}
}
Optional Step 7 - Set Up the Apex Mock test Class (ApplicationFormControllerMock) :
***********************************************************************/
@IsTest
public class ApplicationFormControllerMock implements HttpCalloutMock {
private Integer statusCode;
private String responseBody;
public ApplicationFormControllerMock(Integer statusCode, String responseBody) {
this.statusCode = statusCode;
this.responseBody = responseBody;
}
public HTTPResponse respond(HTTPRequest req) {
HttpResponse res = new HttpResponse();
res.setStatusCode(statusCode);
res.setBody(responseBody);
return res;
}
}
This ApplicationFormController apex class uses the session ID for authentication and constructs a REST API request to create the Application record.
This implementation involves several key components and configurations to ensure the successful creation of an Application record in Salesforce for a Customer Community Plus user.
Conclusion
Building seamless integrations for Salesforce Experience Cloud just became easier and more efficient! With the use of REST API, Lightning Web Components, and session-based authentication, you now have the power to create robust and scalable solutions for your Customer Community Plus users.
Gone are the days of overly complicated workflows—this streamlined approach lets you capture user inputs, process data securely, and create custom records effortlessly. By leveraging session IDs, you maintain strong security without compromising on simplicity, making it an ideal choice for modern community implementations.
From setting up the Experience Cloud user to creating the Application record with precision and control, this solution empowers developers and administrators to deliver exceptional user experiences. Embrace the power of Salesforce REST API and LWC today, and take your development game to the next level.
If you'd like to see the code and resources used in this project, you can access the repository on GitHub.To access the AVENOIRBLOGS repository, click here. Feel free to explore the code and use it as a reference for your own projects.
The future of seamless Experience Cloud functionality is here—don’t miss out!
References
Blog Credit:
M. Gupta
Salesforce Developer
Avenoir Technologies Pvt. Ltd.
Reach us: team@avenoir.ai
Commenti