How do I use the Tooling API to create a new Apex Trigger?

How do I use the Tooling API to create a new Apex Trigger (rather than update an existing one)?

According to the documentation I need to specify the ContentEntityId as an existing Trigger Id. But in my case I don’t have an Id because I’ve trying to create a new sObject.

If I omit the ContentEntityId I get an error back in the SaveResult:

Message: “insufficient access rights on cross-reference id”

The following is more or less a test case in C# that attempts to use the SOAP tooling API to create the new trigger.

SforceService toolingService = //... Get instance of the Tooling API

MetadataContainer container = new MetadataContainer();
container.Name = "Test" + DateTime.Now.Ticks;

SaveResult[] saveResult = toolingService.create(new sObject[] { container });
string metaDataContainerId = saveResult[0].id;

ApexTriggerMember apexTriggerMember = new ApexTriggerMember();
apexTriggerMember.MetadataContainerId = metaDataContainerId;
apexTriggerMember.Body = "trigger TestOpportunityBeforeUpdate on Opportunity (before update) {\n//Horray\n}";
    // Adding this will successfuly update the existing trigger
//apexTriggerMember.ContentEntityId = "01q70000000GuzP";

SaveResult[] triggerSaveResults = toolingService.create(new sObject[] { apexTriggerMember });
Assert.AreEqual(1, triggerSaveResults.Length);
SaveResult triggerSaveResult = triggerSaveResults[0];
if (!triggerSaveResult.success)

ContainerAsyncRequest containerRequest = new ContainerAsyncRequest();
containerRequest.MetadataContainerId = metaDataContainerId;
containerRequest.IsCheckOnly = false;

SaveResult[] containerResults = toolingService.create(new sObject[] { containerRequest });


It turns out that https://[instance] is a special case, and, in the general case (ApexComponent, ApexPage, ApexTrigger) you use the regular REST API sobject URL with the appropriate sObject type.

For ApexTrigger, this would be https://[instance] So to create a trigger:

$ curl -H 'X-PrettyPrint: 1' -H 'Authorization: Bearer 00D...' \
    -H 'Content-Type: application/json' \
    -d '{ "Name" : "TestTrigger", \
          "TableEnumOrId" : "Opportunity",\
          "Body" : "trigger TestTrigger on Opportunity (after insert){}" }' \
  "id" : "01qi0000000DKwyAAG",
  "success" : true,
  "errors" : [ ]

You can see all the code artifact sObject types listed if you GET https://[instance]

$ curl -H 'X-PrettyPrint: 1' -H 'Authorization: Bearer 00Di0000000I4NV!ARgAQDLUBCU38O9RXONyu5C99tcHYYQCc7dOHW8i6ZiGEgPBxyKZwumKsdE69ElKM0ipCD4oCDYbOsmZKNJ3FUqUhsyFk3zu' | grep \"name\"\ :\ \"Apex
    "name" : "ApexClass",
    "name" : "ApexComponent",
    "name" : "ApexLog",
    "name" : "ApexPage",
    "name" : "ApexTestQueueItem",
    "name" : "ApexTestResult",
    "name" : "ApexTrigger",

Source : Link , Question Author : Daniel Ballinger , Answer Author : metadaddy

Leave a Comment