I am new to the language used in salesforce Apex Triggers:
I'm listening to change on a field and sending the current and previous data values to an external API. But I am not able to set the custom fields to send it to the HTTPRequest method present in ContactUpdateToExternalService class with method callApi. I don't want these properties to be Custom fields on SObject. I want to use it just for the current instance of trigger execution.

trigger ContactUpdate on Contact (after update) {
    for (Contact contact : Trigger.New) {
        if (trigger.newMap.get(contact.Id).AccountId != trigger.oldMap.get(contact.Id).AccountId) {
            Map<Object, Object> data = new Map<Object, Object>contact;
            data.previousAccountId = trigger.oldMap.get(contact.Id).AccountId;
            data.currentAccountId = trigger.newMap.get(contact.Id).AccountId;

The data values are sent to external API services.
I don't want these properties added to Contact sObject, when I use the same trigger for before update.

1 Answer 1


Maps need to use get and put, rather than accessed directly. Also, you should use a Map<String, Object> instead of Map<Object, Object>:

Map<String, Object> data = new Map<String, Object>();
data.put('previousAccountId', trigger.oldMap.get(contact.Id).AccountId);
data.put('currentAccountId', trigger.newMap.get(contact.Id).AccountId);

Or, you can do it all in one step:

Map<String, Object> data = new Map<String, Object> {;
  'previousAccountId' => trigger.oldMap.get(contact.Id).AccountId,
  'currentAccountId' => trigger.newMap.get(contact.Id).AccountId

However, please note that because of governor limits, you may run into a snag at either 50 (maximum number of asynchronous calls per transaction) or 100 (maximum callouts per transaction) records in a single trigger (e.g. because of an API mass update), so you will probably want to update ContactUpdateToExternalService to support records in bulk, so that you can write:

String[] payloads = new String[0];
for(Contact contactRecord: Trigger.new) {
  if(Trigger.oldMap.get(record.Id).AccountId != contactRecord.AccountId) {
        new Map<String, Object> {
          'previousAccountId' => trigger.oldMap.get(contact.Id).AccountId,
          'currentAccountId' => contactRecord.AccountId

You'll need to factor in the 100 callout limit in your callApiBulk method, probably by using a Queueable chain (e.g. the Queueable calls itself recursively until all records are sent).

As an aside, you may not have heard of Change Data Capture. This feature in Salesforce lets external systems subscribe to changes automatically. You may want to see if your external system supports CDC.

  • Using Change Data Capture, we listen to every update. right? But I want to get updates on only a few fields on the sObject. In the answer, I want to add new fields to the contact object. But it just creates a new Object with only two fields.
    – ashr81
    Jul 13, 2021 at 18:46
  • @ashr81 Your question wasn't clear on that. You can include the other Contact data if you want by using getPopulatedFieldsAsMap, clone the map, and add in the additional values you want to write.
    – sfdcfox
    Jul 13, 2021 at 20:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .