Usually you are limited to the functions of HTTP GET or HTTP POST in SSJS or AMPscript to send an API call. This severely limits your API capabilities, both internally for Salesforce Marketing Cloud (SFMC) and to any external resource.
Is there any way via AMPScript or SSJS to utilize HTTP methods outside of GET and POST? YOU BET THERE IS.
It took a bit of effort and help from the Support team before I was able to get this solution working….but the solution was the Script.Util.HttpRequest() function!
Although documentation was scant (and still is), through trial and error, we found out that with the Script.Util.HttpRequest() function you actually CAN use:
GET
DELETE
HEAD
OPTIONS
PATCH
POST
PUT
Below is a sample script utilizing this function:
(sample is based on a SFMC REST call to Content Builder API)
<script runat=server> Platform.Load("core", "1.1.1"); var accessToken = {{yourToken}}; var url = 'https://www.exacttargetapis.com/asset/v1/content/assets/{{ContentID}}' var payload = '{{yourPayload}}'; var auth = 'Bearer ' + accessToken; var req = new Script.Util.HttpRequest(url); req.emptyContentHandling = 0; req.retries = 2; req.continueOnError = true; req.contentType = "application/json" req.setHeader("Authorization", auth); req.method = "PUT"; /*** You can change the method here ***/ req.postData = payload; var resp = req.send(); </script>
Script.Util.HttpRequest() almost seems to be a precursor to WSProxy. Although, WSProxy is purely SOAP API based where this function seems to be more based around REST APIs. BUT, the caveat being that it is not nearly as fast as WSProxy, meaning that large volumes or frequencies are more likely to cause issues when using this function.
Lets break down the above script a bit.
var accessToken = {{yourToken}}; var url = 'https://www.exacttargetapis.com/asset/v1/content/assets/{{ContentID}}' var payload = '{{yourPayload}}'; var auth = 'Bearer ' + accessToken;
This part should be fairly self explanatory.
auth is the authorization token (in this sample, the OAuth token you get via API for SFMC.) The assumption being that you have already made the call to the auth URL to receive the token. Its value is the combination of the accessToken (OAuth) and the require prepend of ‘Bearer ‘.
url is the complete url of your API call. This includes the base url, the endpoint and any ‘unique ids’ necessary (e.g. {{ConntentID}} in the sample)
payload this is the xml/json/etc. ‘body’ of your request. If you are doing POST, PUT, PATCH, etc. This is basically the part that tells the endpoint what to do to what. As it varies depending on endpoint and system, I left this as just a variable in the sample.
Note: You must ensure that the payload is a string on submission or it will error. This can be accomplished using Stringify() in SSJS if current payload is an object or array.
var req = new Script.Util.HttpRequest(url); req.emptyContentHandling = 0; req.retries = 2; req.continueOnError = true; req.contentType = "application/json" req.setHeader("Authorization", auth); req.method = "PUT"; /*** You can change the method here ***/ req.postData = payload; var resp = req.send();
req is very similar to WSProxy and is setting up the Request as an object for us to enter information into.
req.emptyContentHandling is actually pretty self explanatory, value of ‘true’ (1) will let the call continue without error if the payload is empty. ‘False’ (0) will cause an error if the payload is empty.
req.retries sets the amount of retry attempts the function will do before failing the call.
req.continueOnError is pretty self explanatory as well. If you have true, it will continue the request regardless of non-fatal errors. On false, it will fail the call if there are any non-fatal errors.
req.contentType is the definition of the content type of the payload.
req.setHeader sets the name/value pairs inside of the header of the API call. In my sample, I included the Authorization header values. To include multiple Headers, you will just create a second req.setHeader call below it with name/value pairing. You do not add into the same function.
e.g.
req.setHeader('Authorization', authToken); req.setHeader('Header2',header2);
req.method is where you would select the method of your call. e.g. PUT, POST, GET, PATCH, DELETE, etc.
req.postData is where the payload we previously created is stored.
req.Send() is then the execution of the fully formed call after all the pieces have been put together.
In the sample, the variable resp is what would contain the response of your API call (likely in a JSON or similar format) for you to view and interact with.
Parsing the Results
Now that we are able to make the call, how do we collect the results? Well first thing to note is that the results are returned in a Script.Util.Response object which is in a CLR format. Without going into details, pretty much this means that the current result is something that you cannot interact with directly – it will take a little bit of finesse to get it into a malleable JSON.
So first things first, we need to change the content returned from CLR to a String. Luckily there is a native Javascript function to do this. String()
. See below for sample of turning your CLR result into a String.
var resultString = String(resp.content)
Now that we have transformed the result into a format that can be read correctly in SFMC SSJS, now what? Well, as a string, the results are not easily parsed or dissected to gather the info – so this is definitely not optimal. Luckily there is another function in SSJS that we can use to assist us in turning this into a JSON – ParseJSON()
.
See below for sample of turning the String into a JSON
var resultJSON = Platform.Function.ParseJSON(String(resp.content));
This will then store the content from the results of the request inside of a JSON, which is easily interacted with via SSJS. From here you can treat this result the same as other arrays or objects and request info accordingly.
For example:
var name = resultJSON[0].name
Would return the value of the key ‘name’ inside the first object inside the array of resultJSON. So if the below were our JSON:
resultJSON = [{name:"John",title:"Mr."},{name:"John Smith",title:"Master"}]
Then the output of name
would be: John
.
thanks , i have taken inspiration from above script. how would you get a value from json returned.
As the value returned from this is in CLR format, you would first need to convert it to a String, then parse it. So likely something like: var myResponseJSON = ParseJSON(String(myResponse)); where myResponse is the return from the Script.Util call. From there you can grab values similar to you would from any other array/object.
Great Post. Could you please check a problem I have which I have shared on Stack Exchange- https://salesforce.stackexchange.com/questions/307345/generating-salesforce-oauth2-token-via-ssjs-returning-empty-response
Basically I am trying to generate a OAuth2 SF token via the REST API call from a CloudPage. But so far I am receiving a blank response. Will be really great if you could direct me in the right direction.
[…] This article pulls from an earlier article I made about Script.Util functions in SSJS (Rest API Method in SSJS). […]
Hi Gortonington, With help of your article i have colned query activity and displayed but i am not getting any results for var name = resultJSON[0].name, when i write (stringify(name)) it is showing null, but after parse results are fetched upon writing. Can suggest what i am missing
Many thanks for this really detailed and interesting article.
Regarding the retries parameter, do you know which HTTP Errors code that are managed by this parameter ? I wondering if it’s covering every http errors or only few.
Regards,
Pierre.
Great article! Thanks Greg!
The variable containing the response object in the “Parsing the Results” section was renamed from “resp” to “result”. It might make the article more clear if the variable name stays the same.
Thanks for the “String” function, it helped me, stuck for half a day on this CLR format !!!
For my case, I didn’t had to add “[0]” in the response, I could use directly then “resultJSON.name”
I want to push the data from Marketing cloud to Account object in salesforce and retrieve the Contactkey and URL from one of the field from the same record I created.