Skip to main content
Outbound Messages in Salesforce
Andrew Tzikas avatar
Written by Andrew Tzikas
Updated over a week ago

What is an Outbound Message in Salesforce?

Outbound messaging allows you to specify that changes to fields within Salesforce trigger messages containing field values to be sent to designated external servers. This can be accomplished using a Salesforce Flow. Essentially, an outbound message is an action that sends data from Salesforce to external servers in SOAP format. When a workflow rule or Salesforce Flow is triggered, outbound messaging uses the notifications() call to send SOAP messages over HTTP(S) to a designated endpoint.

Use Case of Outbound Message

A common use case for workflow outbound messages is to sync third-party systems when specific events occur in Salesforce, such as when an Opportunity record is created or a Lead is converted. To demonstrate such a scenario, we first need to create an endpoint. Since creating an endpoint is outside the scope of this article, I recommend using a free online tool to create a temporary endpoint for receiving and testing the request.

Steps to Testing Your Outbound Messaging:

Method 1: Quick and Simple Test:

Use this method if you are just looking to see what the Outbound Message payload will look like in its Raw Form

Step 1: Use Pipedream and Create a Public Bin

  • Use a third party site such a Pipedream which we will use for this demo - click the link to access Pipedream https://requestbin.com.

    • Note: Instead of clicking on "Create Request Bin" select the "Create a Public Bin Instead" option.

  • Once you create your Public Bin, copy the Public Bin EndPoint URL and navigate over to Salesforce.

Step 2: Creating the Outbound Message in Salesforce

  • In Salesforce, go to Setup and type "Outbound Messages"

  • Click "New Outbound Message"

  • Select the Object on which you want to execute it. Then select the Opportunity object.

  • Give the Outbound Message a Name

  • In the End Point URL, paste the URL from the URL you created in Step 1.

  • In the Available Fields - select all the required fields on your Opportunity Object as well as the additional fields you want to pass over externally.

    • Note selecting the required fields may not be necessary for testing purposes but may be necessary once you build out your external service out later down the road.

Step 3: Create a Record Trigger Flow

  • Create a “Record-Triggered Flow”. Then provide the flow name and select an after event.

  • Enter in your Flow Triggering conditions and any other Elements and logical steps as needed. For the purposes of this article, I have the Outbound Message to be sent out whenever an Opportunity is created or updated and the record is related to my Test Account record I created as I am simply testing the validity of this Outbound Message.

  • Once you are done creating your flow, activate it. Note, debugging the flow will not generate an Outbound Message. Therefore, create or an update a record in scope that you wish to see your Outbound Message get triggered.

Step 4: Testing the Data and seeing the Raw Response in Pipedream.

  • For my test, I just need to create or update an Opportunity record, and ensure it meets the conditions I set out in Step 3.

    • Again, debugging a record in a Flow will not trigger an outbound message to be sent.

  • Go back to your Public Bin you created in Pipedream and see if an Event was posted from Salesforce, coming from your Record Trigger Flow and Outbound Message that you configured.

  • Click on one of the calls and see the response of the payload sent from Salesforce to Pipedream under Body > Raw

Method 2: Building out a Project in Pipedream with your Outbound Message

This method goes into a bit more detail if you're looking to build out more robust workflows within Pipedream to work with Salesforce and other applications. You can skip this step if you already have another Application configured to work with Salesforce Outbound Messages.

Step 1: Create Request Bin

  • Using Pipedream, this time, select "Create Request Bin"

  • Once the Request Bin is created, Copy the URL . This is the Site Endpoint you will be using.

  • Once you create your Request Bin click edit on the top right hand corner.

  • This will then display your Workflow to accept Outbound Messages from Salesforce into Pipedream.

  • You will notice that Pipedream will create a Second Action in the Workflow for you which will generate some example code needed to parse out the data.

  • Under the Second Action, you will need to update your code here - which can be generated using ChatGPT if you provide the fields in scope that you wish to send over from Salesforce that you set in Method 1, Step 2. At the bottom of the article, I have an example code snippet for this.

Step 2: Testing the Data and seeing the Raw Response in Pipedream.

  • Repeating the steps if needed in Method 1, Step 3, create a Record Trigger flow for your Outbound Message.

  • Create or update a Record as needed to trigger the flow in which the Outbound Message action is tied too.

    • Note, debugging a record in a Flow will not trigger an outbound message to be sent.

  • Go back to Pipedream and in your project space, see the POST API calls coming in from Salesforce.

  • Click on one of the calls and see the response of the payload sent from Salesforce to Pipedream under "body"

Step 3: Continue to build out your Workflow as Needed:

  • Once you validated that the fields are coming through, you can continue to build out your Workflow in Pipedream and connect it to the many native apps it supports.

Tracking Outbound Messaging Delivery Statuses:

  • You can track the status of your Outbound Messages by navigating to Setup > Monitoring > Outbound Messages

  • If you see any API Failures you can work with your API Team to fix these. These are most likely due to the fact that the you do not have the necessary fields mapped out on the receiving 3rd party application.

Example Code Snippet

import xml2js from "xml2js";

export default defineComponent({
async run({ steps, $ }) {
const parser = new xml2js.Parser();

// Incoming XML data
const xmlData = steps.trigger.event.body;

// Log the incoming XML data for debugging
console.log("Incoming XML Data:", xmlData);

let parsedData;
try {
parsedData = await parser.parseStringPromise(xmlData);
} catch (error) {
console.error("Error parsing XML:", error);
await $.respond({
status: 400,
body: { error: "Invalid XML format" },
});
return;
}

// Log the parsed XML data for debugging
console.log("Parsed Data:", JSON.stringify(parsedData, null, 2));

// Extract Opportunity fields from the parsed XML
try {
const notification = parsedData["soapenv:Envelope"]["soapenv:Body"][0].notifications[0].Notification[0];
const opportunity = notification.sObject[0];

const opportunityId = opportunity["sf:Id"][0];
const opportunityName = opportunity["sf:Name"][0];
const opportunityAmount = opportunity["sf:Amount"][0];
const closeDate = opportunity["sf:CloseDate"] ? opportunity["sf:CloseDate"][0] : null;
const currencyIsoCode = opportunity["sf:CurrencyIsoCode"] ? opportunity["sf:CurrencyIsoCode"][0] : null;
const forecastCategory = opportunity["sf:ForecastCategory"] ? opportunity["sf:ForecastCategory"][0] : null;
const forecastCategoryName = opportunity["sf:ForecastCategoryName"] ? opportunity["sf:ForecastCategoryName"][0] : null;
const stageName = opportunity["sf:StageName"] ? opportunity["sf:StageName"][0] : null;

// Log extracted fields for debugging
console.log("Opportunity Id:", opportunityId);
console.log("Opportunity Name:", opportunityName);
console.log("Opportunity Amount:", opportunityAmount);
console.log("Close Date:", closeDate);
console.log("Currency ISO Code:", currencyIsoCode);
console.log("Forecast Category:", forecastCategory);
console.log("Forecast Category Name:", forecastCategoryName);
console.log("Stage Name:", stageName);

if (!opportunityId || !opportunityName || !opportunityAmount) {
await $.respond({
status: 400,
body: { error: "Missing required fields" },
});
return;
}

// Prepare the response body
const responseBody = {
opportunityId,
opportunityName,
opportunityAmount,
closeDate,
currencyIsoCode,
forecastCategory,
forecastCategoryName,
stageName,
};

console.log("Response Body:", responseBody);

// Send the response
await $.respond({
status: 200,
headers: { "Content-Type": "application/json" },
body: responseBody,
});
} catch (error) {
console.error("Error extracting fields:", error);
await $.respond({
status: 500,
body: { error: "Error extracting fields" },
});
}
},
});

Did this answer your question?