<img height="1" width="1" style="display:none;" alt="" src="https://ct.pinterest.com/v3/?event=init&amp;tid=2612519005006&amp;noscript=1">
Skip to content
English
  • There are no suggestions because the search field is empty.

How to Trigger a Marqet Workflow from Salesforce

Use this guide to configure Salesforce to automatically send a webhook to Marqet when a record is updated. No third-party tools required. Everything is built using native Salesforce Apex and Named Credentials.

Prerequisites

  • System Administrator access in Salesforce
  • Your Marqet webhook URL (found in your Marqet workflow settings)
  • Access to the Salesforce Developer Console

Step 1: Get your Marqet webhook URL

In Marqet, navigate to your workflow settings and copy the webhook receiver URL. It will look like this:

https://marqet.marq.com/api/webhooks/catch/[your-unique-id]

Keep this handy — you'll need it in step 5.


Step 2: Create an External Credential

In Salesforce, go to Setup → Named Credentials → External Credentials tab → New

Field Value
Label Marq_Webhook_Cred
Name Marq_Webhook_Cred
Authentication Protocol No Authentication

Save, then scroll down to Principals → New:

Field Value
Parameter Name anonymous
Sequence Number 1
Identity Type Anonymous

Save.


Step 3: Create a Named Credential

In Salesforce, go to Setup → Named Credentials → Named Credentials tab → New

Field Value
Label Marq_Webhook
Name Marq_Webhook
URL https://marqet.marq.com
External Credential Marq_Webhook_Cred

Save.


Step 4: Grant permission set access in Salesforce

Users who trigger the webhook need access to the External Credential.

  1. Go to Setup → Permission Sets → New
  2. Name it Webhook_Access, leave License as --None--, and save
  3. Inside the permission set, click External Credential Principal Access → Edit
  4. Move Marq_Webhook_Cred - anonymous to the Enabled column and save
  5. Click Manage Assignments → Add Assignment, find your user, and assign

Note: Any user or automation profile that updates records which trigger the webhook must be assigned this permission set.


Step 5: Deploy the Queueable Apex class

This class handles building the payload and sending the HTTP POST to Marqet. It runs asynchronously so it doesn't block the Salesforce record transaction.

In Salesforce, go to Developer Console → File → New → Apex Class, name it WebhookQueueable, and paste the code for your trigger type below.


Option A: Opportunity stage change (e.g. Closed Won)

WebhookQueueable.cls 

apex
public class WebhookQueueable implements Queueable, Database.AllowsCallouts {     private List<Id> recordIds;      public WebhookQueueable(List<Id> ids) {         this.recordIds = ids;     }      public void execute(QueueableContext ctx) {         for (Id rId : recordIds) {             Opportunity opp = [SELECT Id, Name, StageName, Amount,                                        AccountId, OwnerId, CloseDate                                FROM Opportunity                                WHERE Id = :rId LIMIT 1];              Map<String, Object> payload = new Map<String, Object>{                 'event'         => 'opportunity.closed_won',                 'opportunityId' => opp.Id,                 'name'          => opp.Name,                 'stage'         => opp.StageName,                 'amount'        => opp.Amount,                 'accountId'     => opp.AccountId,                 'ownerId'       => opp.OwnerId,                 'closeDate'     => String.valueOf(opp.CloseDate),                 'changedAt'     => System.now().format()             };              HttpRequest req = new HttpRequest();             req.setEndpoint('callout:Marq_Webhook/api/webhooks/catch/[your-unique-id]');             req.setMethod('POST');             req.setHeader('Content-Type', 'application/json');             req.setBody(JSON.serialize(payload));              Http http = new Http();             HttpResponse res = http.send(req);             System.debug('Webhook response: ' + res.getStatusCode());         }     } }

OpportunityWebhookTrigger.apxt (File → New → Apex Trigger, sObject: Opportunity) 

apex
trigger OpportunityWebhookTrigger on Opportunity (after update) {     List<Id> changedIds = new List<Id>();      for (Opportunity newRec : Trigger.new) {         Opportunity oldRec = Trigger.oldMap.get(newRec.Id);          // Only fires when stage CHANGES to Closed Won         if (newRec.StageName != oldRec.StageName             && newRec.StageName == 'Closed Won') {             changedIds.add(newRec.Id);         }     }      if (!changedIds.isEmpty()) {         System.enqueueJob(new WebhookQueueable(changedIds));     } }

Example payload received by Marqet: 

json
{   "event": "opportunity.closed_won",   "opportunityId": "006...",   "name": "Acme Corp Deal",   "stage": "Closed Won",   "amount": 15000,   "accountId": "001...",   "ownerId": "005...",   "closeDate": "2026-05-27",   "changedAt": "2026-05-27 17:59:44" }

Option B: Contact field change (e.g. status becomes Business Partner)

Update WebhookQueueable.cls with the following execute method, or create a second class (e.g. ContactWebhookQueueable) if you need both running simultaneously:

WebhookQueueable.cls (Contact version)

apex
public class WebhookQueueable implements Queueable, Database.AllowsCallouts {     private List<Id> recordIds;      public WebhookQueueable(List<Id> ids) {         this.recordIds = ids;     }      public void execute(QueueableContext ctx) {         for (Id rId : recordIds) {             Contact c = [SELECT Id, FirstName, LastName, Email,                                 AccountId, Title, Phone                          FROM Contact                          WHERE Id = :rId LIMIT 1];              Map<String, Object> payload = new Map<String, Object>{                 'event'       => 'contact.status_changed',                 'contactId'   => c.Id,                 'firstName'   => c.FirstName,                 'lastName'    => c.LastName,                 'email'       => c.Email,                 'title'       => c.Title,                 'phone'       => c.Phone,                 'accountId'   => c.AccountId,                 'changedAt'   => System.now().format()             };              HttpRequest req = new HttpRequest();             req.setEndpoint('callout:Marq_Webhook/api/webhooks/catch/[your-unique-id]');             req.setMethod('POST');             req.setHeader('Content-Type', 'application/json');             req.setBody(JSON.serialize(payload));              Http http = new Http();             HttpResponse res = http.send(req);             System.debug('Webhook response: ' + res.getStatusCode());         }     } }

ContactWebhookTrigger.apxt (File → New → Apex Trigger, sObject: Contact)

apex
trigger ContactWebhookTrigger on Contact (after update) {     List<Id> changedIds = new List<Id>();      for (Contact newRec : Trigger.new) {         Contact oldRec = Trigger.oldMap.get(newRec.Id);          // Fires when Partner_Status__c changes to "Business Partner"         // Replace Partner_Status__c with your actual field API name         if (newRec.Partner_Status__c != oldRec.Partner_Status__c             && newRec.Partner_Status__c == 'Business Partner') {             changedIds.add(newRec.Id);         }     }      if (!changedIds.isEmpty()) {         System.enqueueJob(new WebhookQueueable(changedIds));     } }

Example payload received by Marqet:

json
{   "event": "contact.status_changed",   "contactId": "003...",   "firstName": "Jane",   "lastName": "Smith",   "email": "jane.smith@example.com",   "title": "VP of Partnerships",   "phone": "+1 (415) 555-0100",   "accountId": "001...",   "changedAt": "2026-05-27 17:59:44" }

Tip: The field Partner_Status__c is an example custom field name. Replace it with the actual API name of the field in your Salesforce org. You can find this under Setup → Object Manager → Contact → Fields & Relationships.


Option C: Account field change (e.g. Type changes to Partner)

AccountWebhookTrigger.apxt (File → New → Apex Trigger, sObject: Account)

apex
trigger AccountWebhookTrigger on Account (after update) {     List<Id> changedIds = new List<Id>();      for (Account newRec : Trigger.new) {         Account oldRec = Trigger.oldMap.get(newRec.Id);          // Fires when Type changes to "Partner"         if (newRec.Type != oldRec.Type             && newRec.Type == 'Partner') {             changedIds.add(newRec.Id);         }     }      if (!changedIds.isEmpty()) {         System.enqueueJob(new WebhookQueueable(changedIds));     } }

Update WebhookQueueable.cls to query Account fields instead:

apex
Account acc = [SELECT Id, Name, Type, Industry, OwnerId, BillingCity, BillingCountry                FROM Account WHERE Id = :rId LIMIT 1];  Map<String, Object> payload = new Map<String, Object>{     'event'     => 'account.type_changed',     'accountId' => acc.Id,     'name'      => acc.Name,     'type'      => acc.Type,     'industry'  => acc.Industry,     'ownerId'   => acc.OwnerId,     'city'      => acc.BillingCity,     'country'   => acc.BillingCountry,     'changedAt' => System.now().format() };

Step 6: Test the integration

To verify the connection before testing a live record, run this in Developer Console → Debug → Open Execute Anonymous Window

apex
HttpRequest req = new HttpRequest(); req.setEndpoint('callout:Marq_Webhook/api/webhooks/catch/[your-unique-id]'); req.setMethod('POST'); req.setHeader('Content-Type', 'application/json'); req.setBody('{"event": "test", "message": "Salesforce connection test"}');  Http http = new Http(); HttpResponse res = http.send(req); System.debug('Status: ' + res.getStatusCode()); System.debug('Body: ' + res.getBody());

Check the Logs tab — you want to see Status: 200. If Marqet receives the payload, the Named Credential is configured correctly.

Then do a live record test:

  1. Open an Opportunity (or Contact/Account depending on your trigger)
  2. Update the relevant field and save
  3. Check your Marqet workflow — the trigger should fire within a few seconds

Troubleshooting

Error Likely cause Fix
We couldn't access the credential Permission set not assigned Assign Webhook_Access permission set to the user (step 4)
Duplicate value found on deploy Class or trigger already exists Open the existing file via File → Open and overwrite the code
No payload in Marqet after record save Trigger condition not met, or wrong field name Check the Developer Console log for a USER_DEBUG line with the HTTP status
Status: 404 Webhook path mismatch Verify the path in your Apex class matches your Marqet URL exactly
Status: 401 or 403 Auth issue on Marqet's side Confirm the webhook URL is active in your Marqet workflow settings

Customizing the trigger condition

The trigger fires based on a field value change. The general pattern is:

apex
if (newRec.YOUR_FIELD__c != oldRec.YOUR_FIELD__c     && newRec.YOUR_FIELD__c == 'YOUR_TARGET_VALUE') {     changedIds.add(newRec.Id); }

To find the correct API field name, go to Setup → Object Manager → [Object] → Fields & Relationships and look in the Field Name column.

You can also trigger on any field change without requiring a specific value:

apex
// Fires whenever the field changes to anything if (newRec.YOUR_FIELD__c != oldRec.YOUR_FIELD__c) {     changedIds.add(newRec.Id); }

Adding payload fields

To include additional Salesforce fields in the payload sent to Marqet, add them to the SELECT query in WebhookQueueable and the payload map:

apex
// In the SELECT: Contact c = [SELECT Id, Email, Custom_Field__c FROM Contact WHERE Id = :rId LIMIT 1];  // In the payload map: 'customField' => c.Custom_Field__c,

For questions or setup support, contact the Support team at support@marq.com