How to create new records in a Data Extension using Async API

How to create new records in a Data Extension using Async API

This article explains how to create new records in a Data Extension using Async API in Salesforce Marketing Cloud.

Insert methods

In server-side JavasScript, there are 3 well known methods for inserting or upserting new records in a Data Extension: Platform, Core and WSProxy.

But, what about the REST? (get it?)

As a matter of fact, Marketing Cloud REST API offers a small range of methods for working with Data Extension records.

They are divided in 2 categories: asynchronous and synchronous. What’s the difference? Let’s find out!

Async vs sync

The terms asynchronous and synchronous are nothing new in the web development and are mostly used in the context of AJAX (Asynchronous JavaScript) requests.

Asynchronous (or Async for short) refers to the type of requests that are performed and then queued in the background, while the rest of our code can work on something else.

Synchronous requests on the other hand, stop the processing of our code and wait for the response before it can continue on further tasks.

Why use async methods?

There are many advantages of using async methods in server-side JavaScript.
Here are some of them:

  • No records are lost when Marketing Cloud servers are unavailable.
  • Processing is faster, as the code doesn’t need to wait for Marketing Cloud to finish inserting new records.
  • Error handling that gives a clear message when an error occurs and doesn’t prevent the rest of the code from executing.

Sounds perfect, but what’s the catch? Well… there are several drawbacks that we need to be aware of:

  • Async requests are managed with REST API, which requires a token to be generated and preferably stored.
  • We can only queue 5MB of data per request, which means that large sets of data need to be split in several parts and processed sequentially.
  • The status and the result of the call need to be performed separately with more REST API requests.

Now that we know what the async requests are and why we would want to use them, let’s try it out!

Before we start

For starters, let’s create a Data Extension with the CustomerKey (or External Key) “S0M3-GU1D-K3Y-G03SR1G4T-H3R3” and the following fields:

Field namePrimary KeyTypeLength
SubscriberKeyYesText50
FirstNameNoText50
LastNameNoText80
EmailAddressNoEmail256

As a second step, we also need the knowledge of how to perform a REST API request and how to store the token. Please refer to my previous article on that matter.

Let’s code!

Insert or upsert a new record

At first, we need to define the records as an array of objects, set as a value of the key “items” in a parent object:

{
	items: [
		{
			SubscriberKey: GUID(),
			FirstName: "John",
			LastName: "Doe",
			EmailAddress: "example@mail.com"
		},
		{
			SubscriberKey: GUID(),
			FirstName: "Jane",
			LastName: "Doe",
			EmailAddress: "example@mail.com"
		}
	]
}

Then, pass the object we just created as the body (or payload) of the request and perform a POST REST API call to this endpoint, where the CustomerKey of our Data Extension is referenced:

/data/v1/async/dataextensions/key:S0M3-GU1D-K3Y-G03SR1G4T-H3R3/rows

Example request

<script runat="server">

    Platform.Load("core", "1");

    var api = new Script.Util.WSProxy();

    var restInstanceUrl = "https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com/",
        accessToken     = "YOUR_REST_API_TOKEN";
	
	try {

        var customerKey = "S0M3-GU1D-K3Y-G03SR1G4T-H3R3";

        var payload = {
            items: [
                {
                    SubscriberKey: GUID(),
                    FirstName: "John",
                    LastName: "Doe",
                    EmailAddress: "example@mail.com"
                },
                {
                    SubscriberKey: GUID(),
                    FirstName: "Jane",
                    LastName: "Doe",
                    EmailAddress: "example@mail.com"
                }
            ]
        }

        var endpoint = restInstanceUrl + "data/v1/async/dataextensions/key:" + customerKey + "/rows";

        var request = new Script.Util.HttpRequest(endpoint);
            request.emptyContentHandling = 0;
            request.retries = 2;
            request.continueOnError = true;
            request.setHeader("Authorization", "Bearer " + accessToken);
            request.method = "POST";
            request.contentType = "application/json";
            request.encoding = "UTF-8";
            request.postData = Stringify(payload);

        var results = request.send();

        var result = Platform.Function.ParseJSON(String(results.content));

        Write(Stringify(result));
		
	} catch(error) {
		
        Write(Stringify(error));
		
    }	

</script>

Note that the method of the request is important: a POST request will insert and a PUT request will upsert a record in a Data Extension.

Example result

Here is the result of the request when no errors have occurred:

{
  "requestId": "S0M3-GU1D-K3Y-1SR1G4T-H3R3",
  "resultMessages": [
    
  ]
}

Check the status

In order to check the status, we need to use the requestId we received as a result from the insert request in the following endpoint:

/data/v1/async/S0M3-GU1D-K3Y-1SR1G4T-H3R3/status

Example request

<script runat="server">

    Platform.Load("core", "1");

    var api = new Script.Util.WSProxy();

    var restInstanceUrl = "https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com/",
        accessToken     = "YOUR_REST_API_TOKEN";
	
	try {

        var requestId = "S0M3-GU1D-K3Y-1SR1G4T-H3R3";

        var endpoint = restInstanceUrl + "data/v1/async/" + requestId + "/status";

        var request = new Script.Util.HttpRequest(endpoint);
            request.emptyContentHandling = 0;
            request.retries = 2;
            request.continueOnError = true;
            request.setHeader("Authorization", "Bearer " + accessToken);
            request.method = "GET";
            request.contentType = "application/json";
            request.encoding = "UTF-8";

        var results = request.send();

        var result = Platform.Function.ParseJSON(String(results.content));

        Write(Stringify(result));
		
	} catch(error) {
		
        Write(Stringify(error));
		
    }	

</script>

Example result

The result has all the useful information we possibly need about our ongoing request.

{
   "status": {
      "callDateTime": "2023-02-20T15:00:00.00",
      "completionDateTime": "2023-02-20T15:01:00.00",
      "hasErrors": false,
      "pickupDateTime": "2023-02-20T15:00:30.00",
      "requestStatus": "Complete",
      "resultStatus": "OK",
      "requestId": "S0M3-GU1D-K3Y-1SR1G4T-H3R3"
   },
   "requestId": "S0M3-GU1D-K3Y-C4NB-H3R3"
}

Retrieve the results

Retrieving the results of the request works in the same manner as retrieving the status.

/data/v1/async/S0M3-GU1D-K3Y-1SR1G4T-H3R3/results

Example request

<script runat="server">

    Platform.Load("core", "1");

    var api = new Script.Util.WSProxy();

    var restInstanceUrl = "https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com/",
        accessToken     = "YOUR_REST_API_TOKEN";
	
	try {

        var requestId = "S0M3-GU1D-K3Y-1SR1G4T-H3R3";

        var endpoint = restInstanceUrl + "data/v1/async/" + requestId + "/results";

        var request = new Script.Util.HttpRequest(endpoint);
            request.emptyContentHandling = 0;
            request.retries = 2;
            request.continueOnError = true;
            request.setHeader("Authorization", "Bearer " + accessToken);
            request.method = "GET";
            request.contentType = "application/json";
            request.encoding = "UTF-8";

        var results = request.send();

        var result = Platform.Function.ParseJSON(String(results.content));

        Write(Stringify(result));
		
	} catch(error) {
		
        Write(Stringify(error));
		
    }	

</script>

Example result

{
    "page": 1,
    "pageSize": 50,
    "count": 1,
    "items": [
        {
            "errorCode": "UnexpectedError",
            "message": "Expect the unexpected!",
            "status": "Error"
        }
    ],
    "requestId": "S0M3-GU1D-K3Y-C4NB-H3R3"
}

Conclusion

That’s it folks! You now have all the tools to try it for yourself!

Using Async API for inserting or upserting records in Data Extensions is certainly more complicated , but when done right have many valuable advantages that outweigh the drawbacks.

Notes

Before testing out the code snippets, please don’t forget to replace these pieces of text with your own values:

  • YOUR_SUBDOMAIN
  • YOUR_REST_API_TOKEN

Have I missed anything?

Please poke me with a sharp comment below or use the contact form.

server-side Javascript
Up Next:

How to increase efficiency by using Batches in server-side JavaScript

How to increase efficiency by using Batches in server-side JavaScript