This guide walks you through setting up a triggered personalization email using:
Apex-defined data source
Flow (On-Demand)
API (cURL)
This class acts as the data contract + formatter for your email.
public class OrderConfirmationContactService {
// ----------------------------
// Basic fields coming from API
// ----------------------------
@AuraEnabled public String LastName { get; set; }
@AuraEnabled public String FirstName { get; set; }
@AuraEnabled public String OrderNumber { get; set; }
@AuraEnabled public String ItemName { get; set; }
@AuraEnabled public String ItemQuantity { get; set; }
@AuraEnabled public String PaymentMethod { get; set; }
// ---------------------------------------
// Formatted fields used directly in email
// ---------------------------------------
@AuraEnabled public String OrderDateYmdJp { get; set; }
@AuraEnabled public String OrderDateYmdSlash { get; set; }
@AuraEnabled public String ItemPriceFormatted { get; set; }
@AuraEnabled public String TotalAmountFormatted { get; set; }
// ------------------------------------
// Internal raw values for calculations
// ------------------------------------
private String orderDateRaw;
private String itemPriceRaw;
private String totalAmountRaw;
// ----------------------------
// OrderDate custom property
// ----------------------------
@AuraEnabled
public String OrderDate {
get {
return orderDateRaw;
}
set {
orderDateRaw = value;
OrderDateYmdJp = null;
OrderDateYmdSlash = null;
if (String.isBlank(orderDateRaw) || orderDateRaw.length() < 10) {
return;
}
Date d = Date.valueOf(orderDateRaw.substring(0, 10));
DateTime dt = DateTime.newInstance(d, Time.newInstance(0, 0, 0, 0));
OrderDateYmdJp = dt.format('yyyy年MM月dd日');
OrderDateYmdSlash = dt.format('yyyy/MM/dd');
}
}
// ----------------------------
// ItemPrice custom property
// ----------------------------
@AuraEnabled
public String ItemPrice {
get {
return itemPriceRaw;
}
set {
itemPriceRaw = value;
ItemPriceFormatted = null;
if (String.isBlank(itemPriceRaw)) {
return;
}
Decimal amount = Decimal.valueOf(itemPriceRaw.replace(',', ''));
ItemPriceFormatted = amount.format();
}
}
// ----------------------------
// TotalAmount custom property
// ----------------------------
@AuraEnabled
public String TotalAmount {
get {
return totalAmountRaw;
}
set {
totalAmountRaw = value;
TotalAmountFormatted = null;
if (String.isBlank(totalAmountRaw)) {
return;
}
Decimal amount = Decimal.valueOf(totalAmountRaw.replace(',', ''));
TotalAmountFormatted = amount.format();
}
}
}
This ensures your Apex logic works and is deployable.
@IsTest
private class OrderConfirmationContactServiceTest {
@IsTest
static void testFormatting() {
OrderConfirmationContactService s = new OrderConfirmationContactService();
s.OrderDate = '2026-02-05';
s.ItemPrice = '2000';
s.TotalAmount = '22000';
System.assertEquals('2026年02月05日', s.OrderDateYmdJp);
System.assertEquals('2026/02/05', s.OrderDateYmdSlash);
System.assertEquals('2,000', s.ItemPriceFormatted);
System.assertEquals('22,000', s.TotalAmountFormatted);
}
@IsTest
static void testBlankValues() {
OrderConfirmationContactService s = new OrderConfirmationContactService();
s.OrderDate = null;
s.ItemPrice = null;
s.TotalAmount = null;
System.assertEquals(null, s.OrderDateYmdJp);
System.assertEquals(null, s.OrderDateYmdSlash);
System.assertEquals(null, s.ItemPriceFormatted);
System.assertEquals(null, s.TotalAmountFormatted);
}
}
Go to Content Builder
Click Create → Email
Choose:
Use Component OR
Build from HTML
Click Data Source → Add
Name: OrderConfirmationSource
Type: Apex
Select Event
Insert fields like:
FirstName
OrderNumber
OrderDateYmdSlash
ItemPriceFormatted
TotalAmountFormatted
👉 These come directly from your Apex class.
Create Autolaunched Flow (No Trigger)
Add Send Email Action
Property
Value
Resource Type
Variable
API Name
orderInput
Data Type
Apex-Defined
Apex Class
OrderConfirmationContactService
Available for Input
✅
👉 This is critical for API-based triggering.
curl --location 'https://yourInstance.my.salesforce.com/services/data/v65.0/actions/custom/flow/Order_Confirmation_Flow' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--data-raw '{
"inputs": [
{
"EmailAddress": "test@example.com",
"IndividualId": "003XXXXXXXXXXXX",
"orderInput": {
"FirstName": "Soumya",
"LastName": "Singh",
"OrderNumber": "ORD-1001",
"ItemName": "Wireless Mouse",
"ItemQuantity": "1",
"PaymentMethod": "Credit Card",
"OrderDate": "2026-02-05",
"ItemPrice": "2000",
"TotalAmount": "22000"
}
}
]
}'
HTTP Status: 200 OK
Flow executes
Email sent
Issue
Fix
401 Unauthorized
Check access token
Flow not triggered
Verify API name
Null values
Ensure input mapping
Apex handles data formatting
Flow handles execution
API enables real-time triggering
Email uses clean personalization fields